Woocommerce Removing required fields from "Additional Information" - php

I have a free product in Woocommerce, and used this tutorial from Skyverge to simplify the checkout process: https://www.skyverge.com/blog/how-to-simplify-free-woocommerce-checkout/
The problem is, for all other products we have 3 required fields in the Additional Information tab:
cracha_empresa
cracha_primeironome
cracha_sobrenome
And we removed "order_notes" all together. To achieve this, we are using the Woocommerce Checkout Field Editor.
When we try to go through the checkout process for this free product, the filter add_filter( 'woocommerce_enable_order_notes_field', '__return_false' ); is removing the additional fields (as expected), but when you try to complete the purchase, I get an error saying that the above fields are REQUIERED to fill out, even though they aren't showing.
From what I guess, I need to filter these fields in an array?
/**
* Remove os cupons, notas, e campos que não são necessários para palestrantes.
*
*/
function sv_free_checkout_fields() {
// Se carrinho precisa de pagamento, não fazer nada
if ( WC()->cart && WC()->cart->needs_payment() ) {
return;
}
// Continuar somente se estamos no checkout
// is_checkout() foi quebrado em WooCommerce 3.2 no ajax, checkar se is_ajax está ativo
if ( function_exists( 'is_checkout' ) && ( is_checkout() || is_ajax() ) ) {
// Remove cupons para produtos gratuitos
remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
// Remove o campo "Additional Info" nas notas dos pedidos
add_filter( 'woocommerce_enable_order_notes_field', '__return_false' );
// Desativa os campos para produtos gratuitos
function unset_unwanted_checkout_fields( $fields ) {
// Adiciona aqui o que deseja remover
// campos: http://docs.woothemes.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/#section-2
$billing_keys = array(
'billing_persontype',
'billing_cpf',
'billing_rg',
'billing_cnpj',
'billing_company',
'billing_phone',
'billing_cellphone',
'billing_address_1',
'billing_address_2',
'billing_neighborhood',
'billing_city',
'billing_postcode',
'billing_country',
'billing_state',
'billing_number',
);
// unset each of those unwanted fields
foreach( $billing_keys as $key ) {
unset( $fields['billing'][ $key ] );
}
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'unset_unwanted_checkout_fields' );
}
}
add_action( 'wp', 'sv_free_checkout_fields' );
I tried this with no luck:
/**
* Remove os cupons, notas, e campos que não são necessários para palestrantes.
*
*/
function sv_free_checkout_fields() {
// Se carrinho precisa de pagamento, não fazer nada
if ( WC()->cart && WC()->cart->needs_payment() ) {
return;
}
// Continuar somente se estamos no checkout
// is_checkout() foi quebrado em WooCommerce 3.2 no ajax, checkar se is_ajax está ativo
if ( function_exists( 'is_checkout' ) && ( is_checkout() || is_ajax() ) ) {
// Remove cupons para produtos gratuitos
remove_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 );
// Remove o campo "Additional Info" nas notas dos pedidos
add_filter( 'woocommerce_enable_order_notes_field', '__return_false' );
// Desativa os campos para produtos gratuitos
function unset_unwanted_checkout_fields( $fields ) {
// Adiciona aqui o que deseja remover
// campos: http://docs.woothemes.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/#section-2
$billing_keys = array(
'billing_persontype',
'billing_cpf',
'billing_rg',
'billing_cnpj',
'billing_company',
'billing_phone',
'billing_cellphone',
'billing_address_1',
'billing_address_2',
'billing_neighborhood',
'billing_city',
'billing_postcode',
'billing_country',
'billing_state',
'billing_number',
);
$order_keys = array(
'cracha_empresa',
'cracha_primeironome',
'cracha_sobrenome',
);
// unset each of those unwanted fields
foreach( $billing_keys as $key ) {
unset( $fields['billing'][ $key ] );
}
// unset each of those unwanted fields
foreach( $order_keys as $key ) {
unset( $fields['order'][ $key ] );
}
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'unset_unwanted_checkout_fields' );
}
}
add_action( 'wp', 'sv_free_checkout_fields' );

Just disable Woocommerce Checkout Field Editor and try this.
You can remove the Additional Information and Order Notes fields in WooCommerce checkout page with 2 filters that you add to your themes functions.php file
// Removes Order Notes Title - Additional Information & Notes Field
add_filter( 'woocommerce_enable_order_notes_field', '__return_false', 9999 );
// Remove Order Notes Field
add_filter( 'woocommerce_checkout_fields' , 'remove_order_notes' );
enter code here
function remove_order_notes( $fields ) {
unset($fields['order']['order_comments']);
return $fields;
}
The first filter woocommerce_enable_order_notes_field is returning false and will not display the ‘Additional Information’ heading and also the order notes field,
I have found it needs to be run with a high priority sometimes, that’s why I have added in the ‘9999’.
The second filter woocommerce_checkout_fields is removing the order notes field.

Related

Change cart discount

TLDR:
I'm trying to remove the discount totals added with a coupon without removing the coupon.
So far the best option seems to be:
$woocommerce->cart->set_discount_total(0);
But it doesn't work.
The full history:
Due some business rules I need to apply the coupon discount to electible products in cart, while the others keep it full price.
After all the validations I'm setting the new price like this:
$cart_item['data']->set_price( $new_price );
And trying to remove the discount totals like this:
$woocommerce->cart->set_discount_total(0);
I can't remove the coupon from the cart because it is the subject of all validations, if it's removed the prices will be back to normal.
I've found the add_fee() method earlier but it mess up too much to be worth as a work around.
Here's the complete code:
It's a WIP and need refactoring, I'm sorry for the big chunk of code.
dd_action( 'woocommerce_before_calculate_totals', 'ne_wc_apply_price_for_seller_restriction_coupons', 999, 1);
function ne_wc_apply_price_for_seller_restriction_coupons( $cart_obj ) {
// var_dump($cart_obj);wp_die();
// This is necessary for WC 3.0+
if ( is_admin() && ! defined( 'DOING_AJAX' ) ){
return;
}
// Avoiding hook repetition (when using price calculations for example)
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ){
return;
}
global $woocommerce;
//Array com os codigos dos cupons no carrinho
$coupon_ids = [];
//Array com os ids do sellers dos cupons
$coupon_seller_ids = [];
// Pegamos os codigos dos cupons existentes no carrinho
if ( count( $coupon_ids ) <= 0) {
$coupon_codes = $cart_obj->get_applied_coupons();
// o carrinho armazena os códigos, não os IDs, então pegamos um por um
foreach ($coupon_codes as $code) {
$coupon = new WC_Coupon($code);
array_push($coupon_ids, $coupon->get_id());
}
}
//Pegamos os sellers de cada cupom
foreach ($coupon_ids as $id) {
$coupon_seller_ids[$id]['ne_wc_sellers'] = get_post_meta( $id, 'ne_wc_sellers', true );
$coupon_seller_ids[$id]['discount_type'] = get_post_meta( $id, 'discount_type', true );
$coupon_seller_ids[$id]['coupon_amount'] = get_post_meta( $id, 'coupon_amount', true );
$coupon_seller_ids[$id]['prorate_quantity'] = 0; // será a quantidade a dividir o valor do cupom entre os itens
$coupon_seller_ids[$id]['prorate_value'] = 0; // será o valor final unitario a subtrair de cada item
}
// Pegamos os produtos do carrinho
$cart_items = $cart_obj->cart_contents;
foreach ($cart_items as $cart_item_key => $cart_item) {
$product_seller_id = get_post_field( 'post_author', $cart_item['data']->get_id() );
//Verificamos se este produto pertece ao seller de um dos cupons
foreach ($coupon_seller_ids as $coupon_id => $coupon_data) {
if ( in_array( $product_seller_id, $coupon_data['ne_wc_sellers'] ) ) {
//guardamos os dados do cupom para fazer o rateio do desconto
$coupon_seller_ids[$coupon_id]['prorate_quantity'] += $cart_item['quantity'];
}
}
}
foreach ($coupon_seller_ids as $id => $coupon_data) {
//para cada tipo de desconto uma abordagem diferente vai ser tomada
switch ($coupon_data['discount_type']) {
//o tipo `fixed_product` concede o desconto no valor unitario do produto
case 'fixed_product':
foreach ( $cart_obj->get_cart() as $cart_item ) {
//novamente pegamos o seller desse produto
$product_seller_id = get_post_field( 'post_author', $cart_item['data']->get_id() );
//verificamos se ele está entre os sellers elegíveis
if ( in_array( $product_seller_id, $coupon_data['ne_wc_sellers'] ) ) {
$current_price = $cart_item['data']->get_price();
$new_price = $current_price - $coupon_seller_ids[$id]['coupon_amount'];
//definimos o novo preço se ele for maior que zero, se não definimos o menor preço possivel
$cart_item['data']->set_price( ($new_price > 0) ? $new_price : 0.01 );
}
}
//removemos o desconto padrão do cupom
$woocommerce->cart->set_discount_total(0);
break;
//o tipo `fixed_cart` rateia o valor total do desconto em cada unidade de produtos elegiveis
case 'fixed_cart':
//calculamos o valor a ser debitado de cada um dos itens
$coupon_seller_ids[$id]['prorate_value'] = $coupon_data['coupon_amount'] / $coupon_data['prorate_quantity'];
foreach ( $cart_obj->get_cart() as $cart_item ) {
$product_seller_id = get_post_field( 'post_author', $cart_item['data']->get_id() );
if ( in_array( $product_seller_id, $coupon_data['ne_wc_sellers'] ) ) {
$current_price = $cart_item['data']->get_price();
$new_price = $current_price - $coupon_seller_ids[$id]['prorate_value'];
//definimos o novo preço se ele for maior que zero, se não definimos o menor preço possivel
$cart_item['data']->set_price( ($new_price > 0) ? $new_price : 0.01 );
}
}
//removemos o desconto padrão do cupom
$woocommerce->cart->set_discount_total(0);
break;
// o tipo `percent` aplicará o desconto percentual sobre o valor unitario do item
case 'percent':
foreach ( $cart_obj->get_cart() as $cart_item ) {
$product_seller_id = get_post_field( 'post_author', $cart_item['data']->get_id() );
if ( in_array( $product_seller_id, $coupon_data['ne_wc_sellers'] ) ) {
$current_price = $cart_item['data']->get_price();
$new_price = $current_price - ($current_price * ($coupon_data['coupon_amount'] / 100));
//definimos o novo preço se ele for maior que zero, se não definimos o menor preço possivel
$cart_item['data']->set_price( ($new_price > 0) ? $new_price : 0.01 );
}
}
//removemos o desconto padrão do cupom
$woocommerce->cart->set_discount_total(0);
break;
default:
# code...
break;
}
}
}

Set My Account custom items endpoints titles in WooCommerce

I customise my woocommerce account pages by adding new endpoints successfully.
The title oh this new endpoints is "My account" default title. I would like to customize the title as well.
I tried with the hook "woocommerce_endpoint_{endpoints}_title", which works perfectly on defaults endpoints, but it doesn't seem to work on custom endpoint :
My custom endpoint (not working):
add_filter( 'woocommerce_endpoint_favoris_title', 'change_my_account_favoris_title', 10, 2 );
function change_my_account_favoris_title( $title, $endpoint ) {
$title = __( "Tests", "woocommerce" );
return $title;
}
Custom endpoint
Default endpooint example working:
add_filter( 'woocommerce_endpoint_edit-account_title', 'change_my_account_edit_title', 10, 2 );
function change_my_account_edit_title( $title, $endpoint ) {
$title = __( "Tests", "woocommerce" );
return $title;
}
Default endpoint
Can't find anything on this for now,
Thanks for your time
EDIT:
My complete hooks of my woocommerce account section:
1/ Creation of endpoints :
add_filter ('woocommerce_account_menu_items', 'custom_log_history_link', 40);
function custom_log_history_link($menu_links){
$menu_links = array_slice( $menu_links, 0, 5, true )
+ array( 'favoris' => 'Mes favoris' )
+ array_slice( $menu_links, 5, NULL, true )
+ array( 'delete-account' => 'Supprimer mon compte' )
+ array_slice( $menu_links, 5, NULL, true );
return $menu_links;
}
add_action( 'init', 'custom_add_endpoint' );
function custom_add_endpoint() {
add_rewrite_endpoint( 'favoris', EP_PAGES );
add_rewrite_endpoint( 'delete-account', EP_PAGES);
}
2/ Content of new endpoints:
add_action( 'woocommerce_account_favoris_endpoint', 'custom_my_account_endpoint_content_favoris' );
function custom_my_account_endpoint_content_favoris() {
$user = wp_get_current_user();
$user_id=$user->ID;
$favoris=get_field('liste_des_favoris','user_'.$user_id);
$favoris_id=array();
echo "<h3>Vos produits favoris :</h3>";
if ($favoris!=''){
foreach ($favoris as $favori) {
$favoris_id[] = $favori['produit_favori'];
}
echo '<ul class="list-produits">';
foreach($favoris as $favori){
$product=wc_get_product($favori['produit_favori']);
$product = $product->get_data();
$sidebar = true;
ItemProduit($product,$sidebar,$favoris_id,$user_id);
}
echo '</ul>';
} else {
echo "<p>Vous n'avez pas de favoris pour le moment1.</p>";
}
}
add_action( 'woocommerce_account_delete-account_endpoint', 'custom_my_account_endpoint_content' );
function custom_my_account_endpoint_content() {
echo "<p>Etes-vous sûr de vouloir supprimer défintivement votre compte ?<br/>Attention ! Toute suppression de compte est définitive, vous perdrez tout l'historique de vos achats.<br/>En supprimant votre compte, toutes vos données personnelles seront définitivement effacées de notre base de données.</p>";
echo '<p class="status"></p>';
wp_nonce_field( 'ajax-delete-nonce', 'delete-security' );
echo '<div class="btns-delete">';
echo '<div class="btn btn-red" id="submit-delete">Supprimer</div>';
echo '</div>';
}
3/ Custom menu order :
add_filter ( 'woocommerce_account_menu_items', 'custom_sort_menu' );
function custom_sort_menu( $menu_links ){
$menu_links = array(
'dashboard' => 'Tableau de bord',
'orders' => 'Mes commandes',
'favoris' => 'Mes favoris',
'edit-address' => 'Mes adresses',
'edit-account' => 'Détails du compte',
'customer-logout' => 'Déconnexion',
'delete-account' => 'Supprimer mon compte',
);
return $menu_links;
}
To allow the composite filter hook woocommerce_endpoint_{$endpoint}_title to work with custom My Account endpoints, there is something missing from your code. You need to declare those endpoints as query vars in woocommerce_get_query_vars filter hook as follows:
add_filter( 'woocommerce_get_query_vars', 'myaccount_custom_endpoints_query_vars' );
function myaccount_custom_endpoints_query_vars( $query_vars ) {
$query_vars['favoris'] = 'favoris';
$query_vars['delete-account'] = 'delete-account';
return $query_vars;
}
Then to change that custom endpoints titles you can use effectively:
add_filter( 'woocommerce_endpoint_favoris_title', 'change_my_account_favoris_title' );
function change_my_account_favoris_title( $title ) {
return __( "Favoris", "woocommerce" );
}
add_filter( 'woocommerce_endpoint_delete-account_title', 'change_my_account_delete_account_title' );
function change_my_account_delete_account_title( $title ) {
return __( "Supprimer mon compte", "woocommerce" );
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Remember to refresh rewrite rules by saving changes on Wordpress settings "Permalinks" section.
Other notes:
In your actual code, you are using 2 times the hook woocommerce_account_menu_items in 2 functions… You need just one of them
One way of changing the title of the custom WooCommerce endpoints is to use the_title filter with the in_the_loop conditional
Here is an example that you'll need to modify per your own requirements.
function wpb_woo_endpoint_title( $title, $id ) {
if ( is_wc_endpoint_url( 'downloads' ) && in_the_loop() ) { // add your endpoint urls
$title = "Download MP3s"; // change your entry-title
}
elseif ( is_wc_endpoint_url( 'orders' ) && in_the_loop() ) {
$title = "My Orders";
}
elseif ( is_wc_endpoint_url( 'edit-account' ) && in_the_loop() ) {
$title = "Change My Details";
}
return $title;
}
add_filter( 'the_title', 'wpb_woo_endpoint_title', 10, 2 );

woocommerce cart with multiple subtotals from same products with multiple prices

I am trying to make a store that the products have multiple prices, one for every supplier. And when i choose the products , show in the cart the prices and subtotals of each supplier. For example, i enter the store, then choose sugar and milk without knowing the prices, proceed to cart and in the cart page i can see: Sugar- Store 1 $10- Store 2 $20 / Milk - Store 1 $20 - Store 2 $30---Subtotal Store 1=$30 Store 2=$50. And that's it, i dont need to proceed with checkout, it's only to compare stores prices from equal products. i try variable products, i get to show the prices on cart but i can't make more than one subtotal array by the variable id. Any ideas?
well, maybe this answer will help someone else in the future, i figure it out, i leave the function here just in case
// Muestra los custom fields en el carrito
add_filter( 'woocommerce_get_item_data', 'super_custom_field', 10, 2 );
function super_custom_field( $cart_data, $cart_item )
{
$items_super = array();
if( !empty( $cart_data ) )
$custom_items = $cart_data;
// Los busca desde el id
$product_id = $cart_item['product_id'];
$supermercado_1 = get_field('super_1',7);
$supermercado_2 = get_field('super_2',7);
$supermercado_3 = get_field('super_3',7);
if( $precio_1 = get_post_meta( $product_id, 'precio_1', true ))
if( $precio_2 = get_post_meta( $product_id, 'precio_2', true ))
if( $precio_3 = get_post_meta( $product_id, 'precio_3', true ))
$items_super[] = array(
'name' => __( 'Precios en supermercados', 'woocommerce'),
'display' => '<div>
<p class="super1 supermercados"><strong>' . ($supermercado_1). '</strong> <span>$' . ($precio_1). '</span></p>
<p class="super2 supermercados"><strong>' . ($supermercado_2). '</strong> <span>$' . ($precio_2). '</span></p>
<p class="super3 supermercados"><strong>' . ($supermercado_3). '</strong> <span>$' . ($precio_3). '</span></p>
</div>',
);
return $items_super;
}
//Suma los custom field de precio 1
//Elige el lugar donde lo muestra
add_filter( 'woocommerce_after_cart_contents', 'suma_precio_1', 10, 2 );
//este es despues del carro antes del checkout
add_action( 'woocommerce_cart_totals_before_shipping', 'suma_precio_1', 20 );
//este es en el checkout
add_action( 'woocommerce_review_order_before_shipping', 'suma_precio_1', 20 );
function suma_precio_1() {
$total_1 = 0;
$supermercado_1 = get_field('super_1',7);
// Busca en el loop del carro el cutom field en cada producto y los suma y multiplica por la cantidad
foreach( WC()->cart->get_cart() as $cart_item ){
$precio_super_1 = (float) get_post_meta( $cart_item['product_id'], 'precio_1', true );
$total_1 += $precio_super_1 * $cart_item['quantity'];
}
if( $total_1 > 0 ){
// The Output
echo ' <tr class="super1">
<td colspan="5"><p><strong>' .$supermercado_1. '</strong></td> <td colspan="" style="text-align:right;"><span>$' . number_format($total_1, 2) . '</span></p></td>
</tr>';
}
}
//Suma los custom field de precio 1
//Elige el lugar donde lo muestra
add_filter( 'woocommerce_after_cart_contents', 'suma_precio_2', 10, 2 );
//este es despues del carro antes del checkout
add_action( 'woocommerce_cart_totals_before_shipping', 'suma_precio_2', 20 );
//este es en el checkout
add_action( 'woocommerce_review_order_before_shipping', 'suma_precio_2', 20 );
function suma_precio_2() {
$total_2 = 0;
$supermercado_2 = get_field('super_2', 7);
// Busca en el loop del carro el cutom field en cada producto y los suma y multiplica por la cantidad
foreach( WC()->cart->get_cart() as $cart_item ){
$precio_super_2 = (float) get_post_meta( $cart_item['product_id'], 'precio_2', true );
$total_2 += $precio_super_2 * $cart_item['quantity'];
}
if( $total_2 > 0 ){
// The Output
echo ' <tr class="super2">
<td colspan="5"><p><strong>' .$supermercado_2. '</strong></td> <td colspan="" style="text-align:right;"><span>$' . number_format($total_2, 2) . '</span></p></td>
</tr>';
}
}
//Suma los custom field de precio 1
//Elige el lugar donde lo muestra
add_filter( 'woocommerce_after_cart_contents', 'suma_precio_3', 10, 2 );
//este es despues del carro antes del checkout
add_action( 'woocommerce_cart_totals_before_shipping', 'suma_precio_3', 20 );
//este es en el checkout
add_action( 'woocommerce_review_order_before_shipping', 'suma_precio_3', 20 );
function suma_precio_3() {
$total_3 = 0;
$supermercado_3 = get_field('super_3', 7);
// Busca en el loop del carro el custom field en cada producto y los suma y multiplica por la cantidad
foreach( WC()->cart->get_cart() as $cart_item ){
$precio_super_3 = (float) get_post_meta( $cart_item['product_id'], 'precio_3', true );
$total_3 += $precio_super_3 * $cart_item['quantity'];
}
if( $total_3 > 0 ){
// The Output
echo ' <tr class="super3">
<td colspan="5"><p><strong>' .$supermercado_3. '</strong></td> <td colspan="" style="text-align:right;"><span>$' . number_format($total_3, 2) . '</span></p></td>
</tr>';
}
}

WooCommerce - Restriction of one category per order

I searched in the different messages but I can't find exactly what I am looking for ... Could you help me?
I found this code which almost matches what I need.
It prevents the addition of new products if a product is already present in the cart.
I would also like to add the additional condition which is that if I have products in my cart, it is not possible to add the product. And show an alert message.
// Add custom Theme Functions here
// Custom conditional function that checks for parent product categories
function has_parent_term( $product_id ) {
// HERE set your targeted product category SLUG
$category_slug = 'box-dejeuner'; // <==== <==== <==== <==== <==== <==== <====
// Convert category term slug to term id
$category_id = get_term_by('slug', $category_slug, 'product_cat')->term_id;
$parent_term_ids = array(); // Initializing
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, 'product_cat' ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
} else {
$parent_term_ids[] = $term->term_id;
}
}
return in_array( $category_id, $parent_term_ids );
}
// Avoid add to cart others product categories when "box-dejeuner" is in cart
add_filter( 'woocommerce_add_to_cart_validation', 'specific_category_avoid_add_to_cart_others', 20, 3 );
function specific_category_avoid_add_to_cart_others( $passed, $product_id, $quantity) {
if( WC()->cart->is_empty() || has_parent_term( $product_id ) ) {
return $passed;
}
foreach( WC()->cart->get_cart() as $cart_item ){
if( has_parent_term( $cart_item['product_id'] ) ) {
wc_add_notice( __('Si une box déjeuner est présente dans votre panier, vous ne pouvez pas commander un autre produit. Veuillez finaliser votre commande de la box et repasser une nouvelles commandes pour vos autres produits. ', 'woocommerce' ), 'error' ); // Display a custom error notice
return false; // Avoid add to cart
}
}
return $passed;
}

Display minimum weight and remaining weight message on cart and checkout page for specific category - WooCommerce

Inspired from Minimum cart amount for specific product categories in WooCommerce I have the following code
add_action( 'woocommerce_check_cart_items', 'checkout_required_min_weight_mood' );
function checkout_required_min_weight_mood () {
// soltanto sulle pagine carrello e check out
if( ! ( is_cart() || is_checkout() ) ) return;
// qui il minimo del peso
$minimum_weight = 20; // 20 kg
// Get the Cart's content total weight
$total_weight = WC()->cart->get_cart_contents_weight();
// Se il peso totale è inferiore al minimo, evitiamo il pagamento e visualizziamo un avviso di errore
if( $total_weight < $minimum_weight ) {
// Visualizza un avviso di errore dinamico
wc_add_notice( sprintf(
'<strong>Il minimo peso di %s è richiesto prima di acquistare.</strong>'
. '<br />Il peso totale dei prodotti nel tuo carrello al momento è di %s',
wc_format_weight($minimum_weight),
wc_format_weight($total_weight)
), 'error' );
}
}
I would have liked it applied to the category (slug: special-box) and hide the "proceed to check out button" until the minimum is reached.
The following code checks whether a product in the shopping cart belongs to the category: special-box and hides the "proceed to checkout button" if the minimum weight has not been reached.
function checkout_required_min_weight_mood () {
// Only on cart and check out pages
if( ! ( is_cart() || is_checkout() ) ) return;
// The minimum weight
$minimum_weight = 20; // 20 kg
// Get the Cart's content total weight
$total_weight = WC()->cart->get_cart_contents_weight();
// Set $cat_in_cart to false
$cat_in_cart = false;
// Loop through all products in the Cart
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// If Cart has category "special-box", set $cat_in_cart to true
if ( has_term( 'special-box', 'product_cat', $cart_item['product_id'] ) ) {
$cat_in_cart = true;
break;
}
}
// If the total weight is less than the minimum, we avoid payment and display an error notice & category is in the Cart
if( $total_weight < $minimum_weight && $cat_in_cart ) {
// Displays a dynamic error warning
wc_add_notice( sprintf(
'<strong>Il minimo peso di %s è richiesto prima di acquistare.</strong>'
. '<br />Il peso totale dei prodotti nel tuo carrello al momento è di %s',
wc_format_weight($minimum_weight),
wc_format_weight($total_weight)
), 'error' );
// Removing the Proceed to checkout button from the Cart page
remove_action( 'woocommerce_proceed_to_checkout','woocommerce_button_proceed_to_checkout', 20);
}
}
add_action( 'woocommerce_check_cart_items', 'checkout_required_min_weight_mood' );

Categories