WooCommerce Print Invoice & Packing Lists - Change Category - php

I've got a WooCommerce store set up with products in several categories and using the Print Invoice & Packing List plugin to generate packing lists for orders.
The plugin orders products by default based on the first category they are listed in, in alphabetical order.
I'm trying to set the plugin to ignore a preset list of categories by ID, so all products will still display, but only listed under the category I've allowed instead of the first category in alphabetical order.
I've read through the Invoice & Packing List dev reference grabbed a SkyVerge snippet and created a custom plugin which will disable categories completely, but can't for the life of me figure out how the WooCommerce hooks should work to ignore certain categories.
This is what I have in the custom plguin at the moment, which simply removes the categories from packing lists:
if ( ! defined( 'ABSPATH' ) )
add_filter( 'wc_pip_packing_list_group_items_by_category', '__return_false' );
function sv_wc_pip_packing_list_grouping( $group_items, $order_id, $document_type ) {
if ( 'pick-list' !== $document_type ) {
return $group_items;
}
$order = wc_get_order( $order_id );
if ( ! $order->is_paid() ) {
return false;
}
return $group_items;
}
add_filter( 'wc_pip_packing_list_group_items_by_category', 'sv_wc_pip_packing_list_grouping', 10, 3 );
Appreciate any help to identify how to define item categories in this function.

i think you could try this, section Document Filters from your documentation link:
wc_pip_packing_list_exclude_item
Params: $exclude, $product, $item, $item_data
Return: (bool)
Filters if an order item should be excluded from the packing list.
in your filter function, you should be able to test the category from $product, or at least get relevant info to query it. Then you just return true or false following the case

Related

Customization on WooCommerce variable product with custom fields

We have created a site using WooCommerce and WordPress with predefined products.
However, Product A must have variations, to resolve this, we added custom fields such as Colors, Dimensions, etc...
Now once the end-users are navigating to the product, we are able to fetch the custom field values. We also modified the UI so that users can pick and choose from these custom fields. (We have a preview of the modifications done via JS/CSS), so for instance, if they choose a green color we use JS to add a layer of green so that the preview is real time.
Now, we have one challenge.
-> What is the best way to go about adding this product PLUS all modifications done to the cart?
So for instance Product A was modified (on the front-end) using data pulled from the custom fields to include Color: Green and Size: 100x100 instead of defaults values. How do we store this and pass the customized product to the cart?
Appreciate the help!. Glad to add more details if something is not clear.
(There are plugins out there that can provide this functionality; Things similar to WooCommerce Product Add-On, etc... However, we have to custom develop the feature.)
It requires some steps.
1). For your product page:
First you might need to add hidden fields to the add to cart form for each custom field like (example):
add_action( 'woocommerce_before_add_to_cart_button', 'add_hidden_empty_input_fields' );
function add_hidden_empty_input_fields() {
?>
<input type="hidden" name="hidden_color" id="hidden_color" value="">
<input type="hidden" name="hidden_dimensions" id="hidden_dimensions" value="">
<?php
}
Then you will have to make some changes to your Javascript code to set the custom fields chosen values in those hidden fields.
2). Pass the custom fields selected values as custom cart item data (example):
add_filter('woocommerce_add_cart_item_data', 'add_custom_field_data', 10, 3 );
function add_custom_field_data( $cart_item_data, $product_id, $variation_id ) {
if ( isset($_POST['hidden_color']) && ! empty($_POST['hidden_color']) ) {
$cart_item_data['color'] = esc_attr($_POST['hidden_color']);
}
if ( isset($_POST['hidden_dimensions']) && ! empty($_POST['hidden_dimensions']) ) {
$cart_item_data['dimensions'] = esc_attr($_POST['hidden_dimensions']);
}
return $cart_item_data;
}
And optionally display values on cart items (example):
add_filter( 'woocommerce_get_item_data', 'display_custom_cart_item_data', 10, 2 );
function display_custom_cart_item_data( $cart_data, $cart_item ) {
if ( isset($cart_item['color']) ) {
$cart_data[] = array( "name" => __("Color"), "value" => $cart_item['color'] );
}
if ( isset($cart_item['dimensions']) ) {
$cart_data[] = array( "name" => __("Dimensions"), "value" => $cart_item['dimensions'] );
}
return $cart_data;
}
3). Save the custom cart item data as custom order item meta data (example):
add_action( 'woocommerce_checkout_create_order_line_item', 'save_custom_order_item_meta_data' , 10, 4 );
function save_custom_order_item_meta_data( $item, $cart_item_key, $values, $order ) {
if ( isset($values['color']) ) {
$item->add_meta_data( __("Color"), $values['color'] );
}
if ( isset($values['dimensions']) ) {
$item->add_meta_data( __("Dimensions"), $values['dimensions'] );
}
}
Note: The data is going to be displayed on everywhere on orders and email notifications.
Code goes in functions.php file of the active child theme (or active theme). It should work.
The variations have a post_id, you would just use the variation post_id instead of the main product one.

Display product custom field as order item meta on WooCommerce admin order pages

I have created my woocommerce products (fruits and vegetables) with a bunch of custom meta data I can correctly input and display them on my website. One of this data is the unit (ie kilos, box of 6, etc.).
On the Admin order page, I'd like to display this "unit" field right below the name of the products (ex : Strawberry - kilo / Eggs - box of 6, etc.).
I have tried the following code and have the following result (see screenshot) :
add_action( 'woocommerce_before_order_itemmeta', 'unit_before_order_itemmeta', 10, 3 );
function unit_before_order_itemmeta( $item_id, $item, $_product ){
if( $unit = $_product->get_meta('unite') ) {
echo '<p>'.$unit.'</p>';}
}
And here is the result :
Screemshot single order page
=> The meta field 'unit' is correctly displayedunder each product, but for some reason it breaks the page and I have a critical error mesage (highlited in red) at the bottom of the page.
I have read a lot of posts here about different way to catch and display (return, print...) my meta data, but I always end up having this critical error.
Could someone help me understand what is wrong with my code?
You need to target order "line" items only and admin to avoid errors, as follow:
add_action( 'woocommerce_before_order_itemmeta', 'unit_before_order_itemmeta', 10, 3 );
function unit_before_order_itemmeta( $item_id, $item, $product ){
// Only "line" items and backend order pages
if( ! ( is_admin() && $item->is_type('line_item') ) ) return;
$unit = $product->get_meta('unite');
if( ! empty($unit) ) {
echo '<p>'.$unit.'</p>';
}
}
It should better work now without errors.

Add extra details Woocommerce order edit pages in admin

Hi I am using Woocommerce version 3.2.6. We have some orders.
I want to add one extra details to orders when the product id is 123 in the order edit page in wordpress backend.
I wanto add this:
Click here to view this
ie: We have order[order id =3723] , and the ordered item id is 123.
Then in http://example.com/wp-admin/post.php?post=3723&action=edit, I want to add the following link below the corresponding item details:
"Click here to view this"
How we can do this ?
Which hook is suitable for this. Actually I am searching in https://docs.woocommerce.com/wc-apidocs/hook-docs.html.
And I found Class WC_Meta_Box_Order_Items. But i don't know how to use this.
The correct code for WooCommerce version 3+ to add a custom link just after line items and only on backend is:
add_action( 'woocommerce_after_order_itemmeta', 'custom_link_after_order_itemmeta', 20, 3 );
function custom_link_after_order_itemmeta( $item_id, $item, $product ) {
// Only for "line item" order items
if( ! $item->is_type('line_item') ) return;
// Only for backend and for product ID 123
if( $product->get_id() == 123 && is_admin() )
echo ''.__("Click here to view this").'';
}
Tested and works
1) Important: Limit the code to order items "line item" type only, to avoid errors on other order items like "shipping", "fee", "discount"...
2) From the WC_Product object to get the product id you will use WC_Data get_id() method.
3) To get the Order ID from WC_Order_Item_Product object you will use WC_Order_Item method get_order_id().
4) You need to add is_admin() in the if statement to restrict the display in backend.
Order Items Meta Box uses html-order-items.php to loop through Order Items which in turn uses html-order-item.php to display each item.
For your purpose you should look inside html-order-item.php for exact place where you would want to insert your code snippet.
I assume woocommerce_after_order_itemmeta action hook is ideal as it will show the link just below meta information of the item. (In case you want to display the link before item meta than use woocommerce_before_order_itemmeta.)
add_action( 'woocommerce_after_order_itemmeta', 'wp177780_order_item_view_link', 10, 3 );
function wp177780_order_item_view_link( $item_id, $item, $_product ){
if( 123 == $_product->id ) {
echo "<a href='http://example.com/new-view/?id=" . $order->id . "'>Click here to view this</a>";
}
}

Alternative way to orderby grouped product child since filter `woocommerce_grouped_children_args` was removed from WooCommerce 3

In Wordpress Woocommerce I have created a grouped product, with lots of sub products (children) in it. I tried searching everywhere, but I can not find a working solution how to orderby them by either SKU or product name. It seems that it's orderby is generated by "Menu Order" only. Although as I have 30+ sub products in these multiple grouped products, it would be extremely time wasting to order them by Menu Order value.
I tried the following code, but it seems that it worked in WC 2.5, but not 3.0+ .
add_filter( 'woocommerce_grouped_children_args',
'so_22661392_grouped_children_args' );
function so_22661392_grouped_children_args( $args ){
$args['meta_key'] = 'sku';
$args['orderby'] = 'meta_value';
$args['order'] = 'ASC';
return $args;
}
I also searched Google for explanations but could not find any. I tried to clear transients, this doesn't work as well:
WooCommerce>System Status>Tools>Clear Transients
The grouped product can be seen on https://plastmet.ee/uus/toode/umartoru-kork-zzo-pealekaiv/ . The html table should match the children below, but it does not. SKU for children is "563/9005", "567/9005" etc..
Any help would be greatly appreciated!
Hopefully I understand the problem correctly:
If we have overriden the template file single-product/add-to-cart/grouped.php, then we could use e.g.:
if( $grouped_products )
usort( $grouped_products, 'wc_products_array_orderby_title' );
to sort the grouped products by title, instead of the default menu ordering.
We could also unregister:
add_action( 'woocommerce_grouped_add_to_cart', 'woocommerce_grouped_add_to_cart', 30 );
with a custom callback instead.
As a last resort one could override the woocommerce_grouped_add_to_cart() function, e.g. within a plugin, to change the menu ordering.
It's defined as:
if ( ! function_exists( 'woocommerce_grouped_add_to_cart' ) ) {
function woocommerce_grouped_add_to_cart() {
global $product;
$products = array_filter( array_map( 'wc_get_product', $product->get_children() ) );
if ( $products ) {
usort( $products, 'wc_products_array_orderby_menu_order' );
wc_get_template( 'single-product/add-to-cart/grouped.php', array(
'grouped_product' => $product,
'grouped_products' => $products,
'quantites_required' => false,
) );
}
}
}
where one could e.g. use wc_products_array_orderby_title instead.

Displaying product custom fields values in the order once processed

On woocommerce, I am using the code below to render some product custom fields, on cart and on 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_data, $cart_item ) {
$custom_items = array();
if( !empty( $cart_data ) ) {
$custom_items = $cart_data;
}
if( isset( $cart_item['wccpf_enter_product_id'] ) ) {
$diamond = $cart_item['wccpf_enter_product_id'];
$pacolor = get_the_terms($diamond, 'pa_color');
foreach ( $pacolor as $pacolor ) {
$color= $pacolor ->name;
}
$custom_items[] = array( "name" => "color", "value" => $color);
}
return $custom_items;
}
How can I display that custom product fields wccpf_enter_product_id' value in orders?
Thanks.
You can use a custom function hooked in woocommerce_add_order_item_meta action hook to achieve this.
You will need first to add an attribute in your products to get a "readable clean label" for your custom field value that is going to appear as order items meta data.
For that you have to create an attribute first and then set it in your product with any value (as you will replace this value in the code below).
See HERE some more explanations about that process…
You will have to replace in my code the 'custom_field_key' by your specific custom key that you will find on wp_woocommerce_order_itemmeta MySQL table for the corresponding item ID for your specific Order ID.
To find the corresponding item ID for the order, you can search in wp_woocommerce_order_items MySQL table with the Order ID…
You will have also to set your correct attribute slug instead of 'pa_your_attribute' to display in your orders the correct label text for this custom field value.
(see below other similar answers references).
So your code will be something like this:
// ADD THE INFORMATION AS META DATA SO THAT IT CAN BE SEEN AS PART OF THE ORDER
add_action('woocommerce_add_order_item_meta','add_and_update_values_to_order_item_meta', 1, 3 );
function add_and_update_values_to_order_item_meta( $item_id, $item_values, $item_key ) {
// Getting your custom product ID value from order item meta
$custom_value = wc_get_order_item_meta( $item_id, 'custom_field_key', true );
// Here you update the attribute value set in your simple product
wc_update_order_item_meta( $item_id, 'pa_your_attribute', $custom_value );
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This should work
Related answers:
Adding user custom field value to order items details
Add custom Product data dynamically as item meta data on the Order
Displaying custom product data in Order items view

Categories