Woocommerce "No Shipping methods" message: Customise message based on the Zipcode customer enters - woocommerce

Our store has been setup to process orders only within Sydney city. We manage this in Woocommerce by setting the allowed postcodes for a Flat Rate Delivery.
We are now extending deliveries to other other areas but only via telephone (no online orders for these new postcodes). Woocommerce displays a standard No Shipping message but we would to customise such that
Customer enters a postcode within the city, allow online orders. No
change to current behaviour.
Customer enters a postcode for which
telephone orders are allowed, show a customised message asking the
customer to make the call.
All other postcodes, disallow orders.
Any technical direction will be greatly appreciated.
Thanks.

Below code should help you. Change the value of array variable $zip_array in both the functions as a comma separated list of zip codes, which you want to show a custom message. Also, change the string value of $custom_msg to your custom message. More details, please refer this article.
// For Cart Page.
add_filter( 'woocommerce_no_shipping_available_html', 'wf_customize_default_message', 10, 1 );
// For Checkout page
add_filter( 'woocommerce_cart_no_shipping_available_html', 'wf_customize_default_message', 10, 1 );
function wf_customize_default_message( $default_msg ) {
$zip_array = array(
'30031',
);
if ( in_array( WC()->customer->get_shipping_postcode() , $zip_array) ) {
$custom_msg = "Call us for quotation - 1-800-XXX-XXXX";
if( empty( $custom_msg ) ) {
return $default_msg;
}
return $custom_msg;
}
return $default_msg;
}
add_filter('woocommerce_package_rates', 'wf_remove_shipping_options_for_particular_zip_codes', 8, 2);
function wf_remove_shipping_options_for_particular_zip_codes($rates, $package)
{
global $woocommerce;
$zip_array = array(
'30031',
);
if ( in_array( $woocommerce->customer->get_shipping_postcode() , $zip_array) ) {
$rates = array();
}
return $rates;
}

Related

Troubleshooting Woocommerce order emails customized according to shipping method

Currently my two options for shipping are regular shipping (using the Flexible Shipping plugin) and local pickup. I would like my Completed Order emails to be customized according to the shipping method used for the order (e.g. I'd like the header to say "We've shipped your order!" for regular shipping and "Your order is ready for pickup!" for local pickup).
Here's my first attempt at modifying the text through my child theme's functions.php (code based on LoicTheAztec answer in this thread). Currently, instead of inserting the desired text, it shows the default text that I entered in Woocommerce>Settings>Emails>Order Completed>Completed order>Email heading, regardless of shipping method selected.
add_action( 'woocommerce_email_header ', 'modify_header_by_shipping', 10, 2 );
function modify_header_by_shipping( $email_heading, $email ) {
// Only modify "Customer Completed Order" email notification
if( 'customer_completed_order' != $email->id ) return;
//Initialize variable
$found = false;
// Get $order object from $email
$order = $email->object;
// Iterating through Order shipping methods
foreach($order->get_shipping_methods() as $value){
$rate_id = $value->get_method_id(); // Get the shipping rate ID
if ( 'shipping_method_0_local_pickup5' == $rate_id )
$found = true;
}
if ($found)
echo '<p>'.__("Your order is ready for pickup!","woocommerce").'</p>';
else
echo '<p>'.__("We've shipped your order!","woocommerce").'</p>';
}
Here's my ordering page: https://carrickseeds.ca/checkout/

In WooCommerce how can I make it so users can only buy 1 product per order and make it so on a specific product they can only buy it once per user?

I'm building a ticketing website for events. I'm using WooCommerce and The Events Calendar plugin.
I've already made it so that users must be logged in to buy a ticket (product).
Then I found this code snippet that would limit it so that only 1 product can be purchased per order
add_filter( 'woocommerce_add_to_cart_validation', 'wc_limit_one_per_order', 10, 2 );
function wc_limit_one_per_order( $passed_validation, $product_id ) {
if ( 31 !== $product_id ) {
return $passed_validation;
}
if ( WC()->cart->get_cart_contents_count() >= 1 ) {
wc_add_notice( __( 'This product cannot be purchased with other products. Please, empty your cart first and then add it again.', 'woocommerce' ), 'error' );
return false;
}
return $passed_validation;
}
This would work, but in the first if statement you can see that the product ID has to be specified. I know I can also change this to an array like if ( ! in_array( $product_id, array( 31, 32, 33 ) ) ) { but the problem is that I would need to keep updating the IDs for every new event. Is there a way to do this so it applies to all products all the time? If not with code then maybe with settings or a plugin?
I also need to prevent customers (users) from returning to the site later and buying another ticket. So, I need to limit specific products so that only 1 of that SKU can be purchased per user account forever, meaning they can't just return to the site and start the buying process again. Is there a way to do this?
Many thanks in advance.
Is there a way to do this so it applies to all products all the time?
Sure. Just force the Cart to empty before adding a new item:
add_filter( 'woocommerce_add_to_cart_validation', 'bbloomer_only_one_in_cart', 9999, 2 );
function bbloomer_only_one_in_cart( $passed, $added_product_id ) {
wc_empty_cart();
return $passed;
}
Source and screenshot: https://www.businessbloomer.com/woocommerce-allow-1-product-cart/
I need to limit specific products so that only 1 of that SKU can be
purchased per user account forever, meaning they can't just return to
the site and start the buying process again
As #7uc1f3r said, please share the code you tried with and then we'll take a look

Is there a hook that precedes Woocommerce API's duplicate SKU check?

I have a site with Woocommerce and WPML + Multilingual Woocommerce installed. My problem is that I try to insert a product as a translation of a previously entered product without being aware of the ID of the main product. If I enter the ID as translation_of it works; both products share the same SKU and the translation has the SKU field disabled, which is how I want it to work. But I don't want to enter translation_of into the data that gets sent to Woocommerce. I want to only use the SKU and then let Wordpress first check if a product with that SKU already exists and replace sku with translation_of if it does.
This is how I went about it:
add_filter('woocommerce_api_create_product_data', '__create_product_data', -100, 2);
function __create_product_data($data, $api) {
if(isset($data['sku']) && $product_id = wc_get_product_id_by_sku($data['sku'])) {
$product_id = apply_filters('wpml_object_id', $product_id, 'product');
$data['translation_of'] = $product_id;
unset($data['sku']);
}
return $data;
}
But it seems to me that execution arrives at this point long after the SKU has been checked, because I noticed that I can return nothing and I still get product_invalid_sku error back. What would be the correct hook or does such a hook even exist?
My own solution:
add_filter('rest_pre_dispatch', '__rest_pre_dispatch', 10, 3);
function __rest_pre_dispatch($result, $server, $request) {
$sku = $request->get_param('sku');
if ($sku) {
$id = wc_get_product_id_by_sku($sku);
if ($id) {
$product_id = apply_filters('wpml_object_id', $id, 'product');
$request->set_param('translation_of', $product_id);
$request->offsetUnset('sku');
}
}
return $result;
}

Woocommerce - Edit account issue

My Woocommerce is setup to generate username automatically. I'm trying to use the code below to change username before save. I would like to change user name to be equal a custom field filled in billing form.
My code is:
function wc_cpf_as_username ( $user_login ) {
if( !empty($_POST['billing_cpf'] ) ) {
$user_login = $_POST['billing_cpf'];
}
elseif (!empty( $_POST['billing_cnpj'] )){
$user_login = $_POST['billing_cnpj'];
}
else{
$user_login = $_POST['billing_email'];
}
return $user_login;
}
add_filter( 'pre_user_login' , 'wc_cpf_as_username' );
The code work to create user, but this code do not work to edit user in my account page (/my-account/edit-account). Woocommerce show success message (Account details changed successfully.), but data is not changed.
I do not know what is the issue.
Could you help me?
Why you are making that complex function if you have a hook available for this. edit_user_profile_update hook i.e. located in /wp-admin/user-edit.php.
update_user_meta($user_id, 'custom_meta_key', $_POST['custom_meta_key']).
update_user_meta thats for update user meta field based on user ID.
add_action('edit_user_profile_update', 'update_extra_profile_fields');
function update_extra_profile_fields($user_id) {
if ( current_user_can('edit_user',$user_id) )
update_user_meta($user_id, 'Custom_field', $_POST['your_field']);
}

How to get ACF data from WooCommerce customers for order export

On a Wordpress-Shop I use WooCommerce (WC) with Advenced-Custom-Fields (ACF)
and WP-All-Import (WPAI) + WP-All-Export (WPAE).
I added a ACF field CustomerNumber to the WC-Customer (which enhanced the WP-User).
On the WPAI-XML-Import I set the CustomerNumber with a value from a ERP.
So all customers have a unique CustomerNumber.
I now need to export the WC-Orders (to import them in the ERP again).
The Order-XML must include the CustomerNumber from the Customer belongs to the Order.
As I see, the other standard fields from the customer – like name and address – are copied automatically to the order (by WooCommerce itself).
My question is now: How I have to do this for the ACF’s?
Did I have to do this by code on my own? Adding the same AC-fields to the WC-Order and hook into the order checkout and copy the values from the customer to the order?
Or is there some kind of setup which do that and which I did not recognize?
Thx
I did not really found an answer.
My current solution is now as I described it in my question.
I added a new rule for these acf to also make them available on the orders.
Then I added a hook to new created orders, determine the acf from the user and copied the necessary values into the order acf.
function di_woocommerce_new_order( $order_id ) {
$order = new WC_Order( $order_id );
if ( !$order ) return;
$customer_id = $order->get_customer_id();
if ( !$customer_id ) return;
$customer = new WC_Customer($customer_id);
if ( !$customer ) return;
$customer_number = $customer->get_meta('customernumber');
if ( !$customer_number ) return;
// add customer number
$order->add_meta_data('customernumber', $customer_number);
// update order modified timestamp
$order->add_meta_data('order_last_updated', current_time( 'mysql' ));
$order->save_meta_data();
}
add_action( 'woocommerce_checkout_order_processed', 'di_woocommerce_new_order', 10, 1);

Resources