I am creating an event ticketing WordPress theme and I am using WooCommerce and Advanced custom fields (ACF) plugins.
I want to update a custom post type called event. With the stock of a specific ticket. That way my client does not need to look at the woo-commerce products page but can just simply open an "Event"
I tried using the update_post_meta hook but that only works when an admin updates the product in the admin tool. Not with a new order.
function sync_product_stock( $meta_id, $post_id, $meta_key, $meta_value ) {
$postType = get_post_type( $post_id );
if ($postType == 'product' ) {
if ( $meta_key == '_stock' ) {
$product = wc_get_product( $post_id );
$eventId = $product->get_attribute( 'event_id' );
$productName = $product->get_name();
if ($productName.include('Early Bird')) {
update_field( 'event_early_bird_group_event_early_bird_amount_of_tickets', $meta_value, $eventId );
} else if ($productName.include('Regular')) {
update_field( 'event_regular_group_event_regular_amount_of_tickets', $meta_value, $eventId );
} else if ($productName.include('Member')) {
// nothing needs to be updated
}
}
}
}
add_action( 'updated_post_meta', 'sync_product_stock', 10, 4);
How can I get notified when the _stock field is updated? (I don't want to handle the stock-keeping myself
There are some mistakes in your code. Try the following using woocommerce hooks:
// On processed update product stock event
add_action( 'woocommerce_updated_product_stock', 'wc_updated_product_stock_callback' );
// On admin single product creation/update
add_action( 'woocommerce_process_product_meta', 'wc_updated_product_stock_callback' );
// On admin single product variation creation/update
add_action( 'woocommerce_save_product_variation', 'wc_updated_product_stock_callback' );
function wc_updated_product_stock_callback( $product_id ) {
// get an instance of the WC_Product Object
$product = wc_get_product( $product_id );
$stock_qty = $product->get_stock_quantity();
$event_id = $product->get_attribute('event_id');
$product_name = $product->get_name();
if ( strpos($product_name, 'Early Bird') !== false ) {
update_field( 'event_early_bird_group_event_early_bird_amount_of_tickets', $stock_qty, $event_id );
} elseif ( strpos($product_name, 'Regular') !== false ) {
update_field( 'event_regular_group_event_regular_amount_of_tickets', $stock_qty, $event_id );
} elseif ( strpos($product_name, 'Member') !== false ) {
// nothing needs to be updated
}
}
Code goes in function.php file of the active child theme (or active theme). It should work.
Related
I have two shipment class for my products based on their category. Each time after updating a product, it loose the shipment class and I have no idea why.
However I tried to assign proper shipment class to products "on save" programmatically:
specified categories => 1001
else => 1002
Here is my code:
add_action( 'added_post_meta', 'woo_on_product_save', 10, 4 );
add_action( 'updated_post_meta', 'woo_on_product_save', 10, 4 );
function woo_on_product_save( $meta_id, $post_id, $meta_key, $meta_value ) {
if ( $meta_key == '_edit_lock' ) {
if ( get_post_type( $post_id ) == 'product' ) {
if (has_term('fastfood','product_cat')||has_term('coffee','product_cat')){
$shipping_class_type=1001;
}
else{
$shipping_class_type=1002;
}
$product = wc_get_product( $post_id );
$product->set_shipping_class_id( $shipping_class_type );
$product->save();
}
}
}
But this doesn't work as expected. When I make changes on any product(Even products in specified categories) the shipment class always become 1002.
Can you tell me what I am doing wrong?
Updated - Instead try the following with a different hook (untested):
add_action( 'woocommerce_process_product_meta', 'woo_on_product_save', 100 );
function woo_on_product_save( $post_id ) {
if ( has_term( array('fastfood', 'coffee'), 'product_cat', $post_id ) ) {
$shipping_class_id = 1001;
} else {
$shipping_class_id = 1002;
}
$product = wc_get_product( $post_id );
$product->set_shipping_class_id( $shipping_class_id );
$product->save();
}
Code goes in functions.php file of the active child theme (or active theme). It could works.
Note: you need to be sure that 1001 and 1002 exist as shipping class ID.
The following code add a custom field to admin product settings to manage guest checkout at product level:
// Display Guest Checkout Field
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );
function woo_add_custom_general_fields() {
global $woocommerce, $post;
echo '<div class="options_group">';
// Checkbox
woocommerce_wp_checkbox( array(
'id' => '_allow_guest_checkout',
'wrapper_class' => 'show_if_simple',
'label' => __('Checkout', 'woocommerce' ),
'description' => __('Allow Guest Checkout', 'woocommerce' )
) );
echo '</div>';
}
// Save Guest Checkout Field
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields_save( $post_id ){
$woocommerce_checkbox = isset( $_POST['_allow_guest_checkout'] ) ? 'yes' : 'no';
update_post_meta( $post_id, '_allow_guest_checkout', $woocommerce_checkbox );
}
// Enable Guest Checkout on Certain products
add_filter( 'pre_option_woocommerce_enable_guest_checkout', 'enable_guest_checkout_based_on_product' );
function enable_guest_checkout_based_on_product( $value ) {
if ( WC()->cart ) {
$cart = WC()->cart->get_cart();
foreach ( $cart as $item ) {
if ( get_post_meta( $item['product_id'], '_allow_guest_checkout', true ) == 'yes' ) {
$value = "yes";
} else {
$value = "no";
break;
}
}
}
return $value;
}
But it doesn't work actually. What I am doing wrong? How can I fix it?
I am trying to allow guest purchases for specific products. The admin custom field display and save custom field value is working (the 2 first functions), But login/register never comes up on checkout page, even if there are products in cart that doesn't allow guest checkout.
The filter hook enable_guest_checkout_based_on_product doesn't exist anymore and has been replaced by another hook a bit different.
So your code is going to be:
add_filter( 'woocommerce_checkout_registration_required', 'change_tax_class_user_role', 900 );
function change_tax_class_user_role( $registration_required ) {
if ( ! WC()->cart->is_empty() ) {
$registration_required = false; // Initializing (allowing guest checkout by default)
// Loop through cart items
foreach ( WC()->cart->get_cart() as $item ) {
// Check if there is any item in cart that has not the option "Guest checkout allowed"
if ( get_post_meta( $item['product_id'], '_allow_guest_checkout', true ) !== 'yes' ) {
return true; // Found: Force checkout user registration and exit
}
}
}
return $registration_required;
}
Code goes in functions.php file of your active child theme (or active theme). It should works.
Related continuation: Redirection for non checkout guest allowed in WooCommerce
I'm trying to display custom product field checkout_name on the checkout page but I can't seem to figure out how. I'm following checkout hooks visual guide from here.
add_action( 'woocommerce_checkout_before_customer_details', 'custom_before_checkout_form', 10 );
function custom_before_checkout_form( $cart_data ){
$meta_key = 'checkout_name';
$product_id = $cart_item['product_id'];
$meta_value = get_post_meta( $product_id, $meta_key, true );
if( !empty( $cart_data ) )
$custom_items = $cart_data;
if( !empty($meta_value) ) {
$custom_items[] = array(
'key' => __('Store Name', 'woocommerce'),
'value' => $meta_value,
'display' => $meta_value,
);
}
return $custom_items;
}
Custom checkout fields need to be inside the checkout form. If not the field values are not posted on submission.
There is also some errors in your code. Try the following instead using a hook located inside the checkout form, just before billing fields (assuming that the custom product field checkout_name exist).
add_action( 'woocommerce_checkout_before_customer_details', 'custom_before_checkout_form' );
function custom_before_checkout_form(){
// Loop though cart items
foreach ( WC()->cart->get_cart() as $item ) {
// Get the WC_Product Object
$product = $item['data'];
echo '<div align="center">' . $product->get_meta( 'checkout_name' ) . '</div><br>';
}
}
Code goes in functions.php file of your active child theme (or active theme). It should better work.
In WooCommerce and I have added a custom field "description" for each product.
I was able to find a way to show both, the label name and the value:
add_filter( 'woocommerce_add_cart_item_data', 'save_days_field', 10, 2 );
function save_days_field( $cart_item_data, $product_id ) {
$special_item = get_post_meta( $product_id , 'description',true );
if(!empty($special_item)) {
$cart_item_data[ 'description' ] = $special_item;
// below statement make sure every add to cart action as unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'description', $special_item );
}
return $cart_item_data;
}
// Render meta on cart and checkout
add_filter( 'woocommerce_get_item_data','rendering_meta_field_on_cart_and_checkout', 10, 2 );
function rendering_meta_field_on_cart_and_checkout( $cart_item_data, $cart_item ) {
if( isset( $cart_item['description'] ) ) {
$cart_item_data[] = array( "name" => __( "Description", "woocommerce" ), "value" => $cart_item['description'] );
}
return $cart_item_data;
}
Now I need to display ONLY the value (not the label name "Description") of this custom field in the cart and checkout table. I need to display with <small>, like the attribute I am displaying with this code:
add_filter('woocommerce_cart_item_name', 'wp_woo_cart_attributes', 10, 2);
function wp_woo_cart_attributes($cart_item, $cart_item_key){
$productId = $cart_item_key['product_id'];
$product = wc_get_product($productId);
$taxonomy = 'pa_color';
$value = $product->get_attribute($taxonomy);
if ($value) {
$label = get_taxonomy($taxonomy)->labels->singular_name;
$cart_item .= "<small>$value</small>";
}
return $cart_item;
}
How can I make it for this custom field, displaying the value only?
You don't need to include a product custom field as custom cart item data, as it's directly accessible from the product object (or the product ID).
Note: On a cart item variable $cart_item, the WC_Product Object is included and available using $cart_item['data'].
Try the following to add a custom field after the item name in cart and checkout pages:
// Display in cart and checkout pages
add_filter( 'woocommerce_cart_item_name', 'customizing_cart_item_name', 10, 3 );
function customizing_cart_item_name( $product_name, $cart_item, $cart_item_key ) {
$product = $cart_item['data']; // Get the WC_Product Object
if ( $value = $product->get_meta('description') ) {
$product_name .= '<small>'.$value.'</small>';
}
return $product_name;
}
To display it on orders and email notifications use:
// Display in orders and email notifications
add_filter( 'woocommerce_order_item_name', 'customizing_order_item_name', 10, 2 );
function customizing_order_item_name( $product_name, $item ) {
$product = $item->get_product(); // Get the WC_Product Object
if ( $value = $product->get_meta('description') ) {
$product_name .= '<small>'.$value.'</small>';
}
return $product_name;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
i have a api from another wocommerce website and take some information with my product sku
how can i add this information to post meta after created new product ?
i wanna when i create a product , the information take with api and product sku and save to post meta.
i found this hook but i think this not working
<?PHP
function my_product_att( $sku ) {
// my api codes and take information and use
add_post_meta('product_id','key','value');
// i haven't problem here i just need Appropriate hook
}
add_action( 'save_post', 'my_product_att' ); // this hook not work for woocommerce
Woocommerce Products are wordPress posts. You can use wordpress hooks like save_post & $post_id as its argument. You are passing $sku which is wrong.
add_action( 'save_post', 'wpse_110037_new_posts' );
function wpse_110037_new_posts($post_id){
$post_type = get_post_type($post_id);
if($post_type == 'products') {
add_post_meta($post_id,'key','value');
}
}
Try below code. Note that in code $unique is true or false based on if meta value should be unique or not.
add_action('transition_post_status', 'product_created_function', 10, 3);
function product_created_function($newstatus, $oldstatus, $post) {
if($oldstatus != 'publish' && $newstatus == 'publish' && !empty($post->ID) && in_array( $post->post_type, array( 'product') ) ) {
add_post_meta( $post->ID, $key, $value,$unique );
}
}
add_action( 'save_post', 'prowp_save_meta_boxdddd' );
function prowp_save_meta_boxdddd( $post_id ) {
global $wpdb;
$table_prefix = $wpdb->prefix;
$tablename = $table_prefix.'postmeta';
$wpdb->query($wpdb->prepare('UPDATE '.$tablename.' SET meta_value="test" WHERE post_id='.$post_id));
}