I have written a script that, among other things, shows me how many days ago a product was updated/modified. Everything works perfectly, however it has become evident to me that get_date_modified() is returning the date/time of the last time the product was ordered.
I have a custom script that is reducing stock based on an attribute. I believe this is the culprit. I would like date_modified not to update on stock change via purchase, only when the product is manually updated.
How can I bypass the updating of date_modified when this function fires? Is there a filter that can be utilized perhaps?
Stock reduction code:
// ---------------------------------------------------------------------------------------- //
// -------------------------- REDUCE WEIGHT BASED ON WEIGHT FIELD ----------------------- //
// ---------------------------------------------------------------------------------------- //
// reduce stock based on 'pa_weight' attribute
add_filter( 'woocommerce_order_item_quantity', 'filter_order_item_quantity', 10, 3 );
function filter_order_item_quantity( $quantity, $order, $item )
{
$product = $item->get_product();
$term_name = $product->get_attribute('pa_weight');
// 'pa_weight' - keep only the numbers
$quantity = preg_replace('/[^0-9.]+/', '', $term_name);
// new quantity
if( is_numeric ( $quantity ) && $quantity != 0 )
$quantity *= $quantity;
return $quantity;
}
/**
* Order change stock reduction fix.
*
* #param $prevent
* #param $item
* #param $item_quantity
* #return bool|mixed
*/
function custom_stock_reduction_order_change( $prevent, $item, $item_quantity ) {
$stock_reduced = wc_stock_amount( $item->get_meta( '_reduced_stock', true ) );
$stock_reduction = filter_order_item_quantity( $item->get_quantity(), null, $item );
if ( $stock_reduction == $stock_reduced ) {
$prevent = true;
}
return $prevent;
}
add_filter( 'woocommerce_prevent_adjust_line_item_product_stock', 'custom_stock_reduction_order_change', 10, 3 );
Wordpress Site : Woocommerce Plugin
I have multiple meta product fields that I need to export.
I have looked up the reference in WooCommerce Product CSV Importer & Exporter Documentation but I am having a little trouble understanding how to expand the example to add more than one custom column.
This part I am fine with
$columns is an array
So all I need to do is add an array item for each custom field.
/**
* Add the custom column to the exporter and the exporter column menu.
*
* #param array $columns
* #return array $columns
*/
function add_export_column( $columns ) {
// column slug => column name
$columns['my_custom_supplier_product_code'] = 'Supplier Product CODE';
$columns['my_custom_supplier_product_desc'] = 'Supplier Product DESC';
return $columns;
}
add_filter( 'woocommerce_product_export_column_names', 'add_export_column' );
add_filter( 'woocommerce_product_export_product_default_columns', 'add_export_column' );
Here I am not quite sure what to do
REFERENCE
/**
* Provide the data to be exported for one item in the column.
*
* #param mixed $value (default: '')
* #param WC_Product $product
* #return mixed $value - Should be in a format that can be output into a text file (string, numeric, etc).
*/
function add_export_data( $value, $product ) {
$value = $product->get_meta( 'custom_column', true, 'edit' );
return $value;
}
// Filter you want to hook into will be: 'woocommerce_product_export_product_column_{$column_slug}'.
add_filter( 'woocommerce_product_export_product_column_custom_column', 'add_export_data', 10, 2 );
My mod for my first custom column
/**
* Provide the data to be exported for one item in the column.
*
* #param mixed $value (default: '')
* #param WC_Product $product
* #return mixed $value - Should be in a format that can be output into a text file (string, numeric, etc).
*/
function add_export_data( $value, $product ) {
$value = $product->get_meta( 'my_custom_supplier_product_code', true, 'edit' );
return $value;
}
// Filter you want to hook into will be: 'woocommerce_product_export_product_column_{$column_slug}'.
add_filter( 'woocommerce_product_export_product_column_my_custom_supplier_product_code', 'add_export_data', 10, 2 );
Now how do I add what is required for my second column ?
Should I have
2 x add_export_data functions
2 x add_filter
/**
* Provide the data to be exported for one item in CUSTOM COLUMN 1
*
* #param mixed $value (default: '')
* #param WC_Product $product
* #return mixed $value - Should be in a format that can be output into a text file (string, numeric, etc).
*/
function add_export_data_my_custom_supplier_product_code( $value, $product ) {
$value = $product->get_meta( 'my_custom_supplier_product_code', true, 'edit' );
return $value;
}
// Filter you want to hook into will be: 'woocommerce_product_export_product_column_{$column_slug}'.
add_filter( 'woocommerce_product_export_product_column_my_custom_supplier_product_code', 'add_export_data_my_custom_supplier_product_code', 10, 2 );
/**
* Provide the data to be exported for one item in CUSTOM COLUMN 2
*
* #param mixed $value (default: '')
* #param WC_Product $product
* #return mixed $value - Should be in a format that can be output into a text file (string, numeric, etc).
*/
function add_export_data_my_custom_supplier_product_desc( $value, $product ) {
$value = $product->get_meta( 'my_custom_supplier_product_desc', true, 'edit' );
return $value;
}
// Filter you want to hook into will be: 'woocommerce_product_export_product_column_{$column_slug}'.
add_filter( 'woocommerce_product_export_product_column_my_custom_supplier_product_desc', 'add_export_data_my_custom_supplier_product_desc', 10, 2 );
Note that I have tried the code as above, but for some reason
ALL of my columns appear in the spreadsheet
SOME are empty and are not pulling the data from the Product Custom Fields
Rather than 'hacking around' trying to fix the issue, I am now stepping back to try to get a better understanding of how this works.
Thanks
Answering my own question here, and a suggestion that may help others.
Yes, I was correct in my code snippet above.
It does work as expected.
#CBroe was correct:
Maybe start by double-checking the spellings everywhere. The name of
the hooks seem to be related directly to the column slugs, so even the
tiniest misspelling there will likely cause it to not call any
function for the field in question.
My issues were essentially finger trouble
I have 11 Custom Fields.
That gets a little unwieldy when the custom_field_slug references get separated by other code.
So I am adding here
a breakdown to explain what steps are needed
and a formatting suggestion that has made life a lot easier for me to scan across a whole group of related items to make sure I haven't got any typos
STEP 1 : Add Custom Columns to Array for Mapping
/* [ mycode ] EXPORT : ADD custom columns to Exporter
------------------------------------------------------------------------------*/
/**
* Add the custom columns to the exporter and the exporter column menu.
*
* #param array $columns
* #return array $columns
*
*/
function add_export_columns( $columns ) {
// ---------------------------------------------------- Company SYSTEM Fields
// column slug > column name
$columns['company_system_item_code'] = 'Company SYSTEM Item Code';
$columns['company_system_item_description'] = 'Company SYSTEM Item Description';
$columns['company_system_item_category'] = 'Company SYSTEM Item Category';
$columns['company_system_item_unit_weight'] = 'Company SYSTEM Item Unit Weight';
$columns['company_system_item_unit_price'] = 'Company SYSTEM Item Unit Price';
// ---------------------------------------------------- Company WEBSITE Fields
// column slug > column name
$columns['company_website_discount_percent'] = 'Company WEBSITE Discount Percent';
$columns['company_website_item_unit_price'] = 'Company WEBSITE Item Unit Price';
$columns['company_website_item_minimum_units'] = 'Company WEBSITE Item Minimum Units';
// ---------------------------------------------------- Company SUPPLIER Fields
// column slug > column name
$columns['company_supplier_item_code'] = 'Company_SUPPLIER Item Code';
$columns['company_supplier_item_description'] = 'Company SUPPLIER Item Description';
$columns['company_supplier_item_unit_price'] = 'Company SUPPLIER Item Unit Price';
return $columns;
}
add_filter( 'woocommerce_product_export_column_names', 'add_export_columns' );
add_filter( 'woocommerce_product_export_product_default_columns', 'add_export_columns' );
STEP 2 : All the Export Data Functions
/* [ mycode ] EXPORT : GET data to be exported
------------------------------------------------------------------------------*/
/**
*
* Functions to provide the data to be exported for one item in EACH column.
*
*/
// ------------------------------------------------------- Company SYSTEM Fields
function add_export_data_company_system_item_code( $value, $product ) {
$value = $product->get_meta( 'company_system_item_code', true, 'edit' );
return $value;
}
function add_export_data_company_system_item_description( $value, $product ) {
$value = $product->get_meta( 'company_system_item_description', true, 'edit' );
return $value;
}
function add_export_data_company_system_item_category( $value, $product ) {
$value = $product->get_meta( 'company_system_item_category', true, 'edit' );
return $value;
}
function add_export_data_company_system_item_unit_weight( $value, $product ) {
$value = $product->get_meta( 'company_system_item_unit_weight', true, 'edit' );
return $value;
}
function add_export_data_company_system_item_unit_price( $value, $product ) {
$value = $product->get_meta( 'company_system_item_unit_price', true, 'edit' );
return $value;
}
// ------------------------------------------------------- Company WEBSITE Fields
function add_export_data_company_website_discount_percent( $value, $product ) {
$value = $product->get_meta( 'company_website_discount_percent', true, 'edit' );
return $value;
}
function add_export_data_company_website_item_unit_price( $value, $product ) {
$value = $product->get_meta( 'company_website_item_unit_price', true, 'edit' );
return $value;
}
function add_export_data_company_website_item_minimum_units( $value, $product ) {
$value = $product->get_meta( 'company_website_item_minimum_units', true, 'edit' );
return $value;
}
// ------------------------------------------------------- Company SUPPLIER Fields
function add_export_data_company_supplier_item_code( $value, $product ) {
$value = $product->get_meta( 'company_supplier_item_code', true, 'edit' );
return $value;
}
function add_export_data_company_supplier_item_description( $value, $product ) {
$value = $product->get_meta( 'company_supplier_item_description', true, 'edit' );
return $value;
}
function add_export_data_company_supplier_item_unit_price( $value, $product ) {
$value = $product->get_meta( 'company_supplier_item_unit_price', true, 'edit' );
return $value;
}
STEP 3 : All the Filters
/**
*
* Add filters to hook in for EACH column
*
*/
// ------------------------------------------------------- Company SYSTEM Fields
add_filter( 'woocommerce_product_export_product_column_company_system_item_code' , 'add_export_data_company_system_item_code', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_system_item_description' , 'add_export_data_company_system_item_description', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_system_item_category' , 'add_export_data_company_system_item_category', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_system_item_unit_weight' , 'add_export_data_company_system_item_unit_weight', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_system_item_unit_price' , 'add_export_data_company_system_item_unit_price', 10, 2 );
// ------------------------------------------------------- Company WEBSITE Fields
add_filter( 'woocommerce_product_export_product_column_company_website_discount_percent' , 'add_export_data_company_website_discount_percent', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_website_item_unit_price' , 'add_export_data_company_website_item_unit_price', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_website_item_minimum_units', 'add_export_data_company_website_item_minimum_units', 10, 2 );
// ------------------------------------------------------- Company SUPPLIER Fields
add_filter( 'woocommerce_product_export_product_column_company_supplier_item_code' , 'add_export_data_company_supplier_item_code', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_supplier_item_description' , 'add_export_data_company_supplier_item_description', 10, 2 );
add_filter( 'woocommerce_product_export_product_column_company_supplier_item_unit_price' , 'add_export_data_company_supplier_item_unit_price', 10, 2 );
NOTE also the white space padding I used to align the components.
When you have many column slugs of different length, it's quite awkward to scan for errors.
If you don't have every hook and every function named correctly with the appropriate column slugs, then you won't get the expected results.
Hopefully this worked example may be useful for someone else in future.
I try to get the active tax-classes in Woocommerce in my custom plugin. When I use the WC_Tax::get_tax_classes(), I get a empty array.
How does WC_tax class work without order details and run by itself?
WC_Tax::get_tax_classes() returns an empty array when there is only the default tax class set in WooCommerce > Tax (tab) settings.
It's used for example in wc_get_product_tax_class_options() function that displays the available tax classes in admin product pages settings:
/**
* Get product tax class options.
*
* #since 3.0.0
* #return array
*/
function wc_get_product_tax_class_options() {
$tax_classes = WC_Tax::get_tax_classes();
$tax_class_options = array();
$tax_class_options[''] = __( 'Standard', 'woocommerce' );
if ( ! empty( $tax_classes ) ) {
foreach ( $tax_classes as $class ) {
$tax_class_options[ sanitize_title( $class ) ] = $class;
}
}
return $tax_class_options;
}
So the default tax class (active tax class) has no entry when using WC_Tax::get_tax_classes().
Then you can use wc_get_product_tax_class_options() function to get all WooCommerce tax classes or the code from this function if you want something more custom.
Related: How to get the available tax rates in WooCommerce
I am trying to set a variation's maximum quantity allowance based on the value of a one of its custom fields.
Everything is good - the code is working below, however rather than $quantity = round(9/3); I want the value to be $quantity = round($quantity/$weight);
The issue I am having (and have had numerous times in the past with other functions) is that I can't for the life of me seem to pull the correct 'Custom_Field' data. Everything I try returns either boolean false or string Length(0). When I do a var_dump($variation_ID) I get a ton of data, but my custom field is not there.
This is strange, because the data is pulled in other functions I have - but not in this situation and I can't figure out why.
// On single product pages
add_filter( 'woocommerce_available_variation', 'customizing_available_variation', 10, 3 );
function customizing_available_variation( $args, $product_id, $variation_id ) {
$product = wc_get_product ( $product_id );
$weight = get_post_meta( $variation_ID, 'custom_field', true );
$product_stock = $product_id->get_stock_quantity();
var_dump($variation_id);
$quantity = round(9/3);
if( is_woocommerce() ){
$args['max_qty'] = $quantity;
}
return $args;
}
woocommerce_available_variation passes three arguments, the third one being a WC_Product_Variation (that's why you're getting a ton of data when var_dump-ing it).
You've named your third argument $variation_id, which probably led you to treating it as a post/product id.
Meaning, you're trying to pass a WC_Product_Variation as an id to get_post_meta():
$weight = get_post_meta( $variation_ID, 'custom_field', true );
You're also doing the same thing for the second argument (which is the product, not the product id).
You just have to get the variation id and pass that instead:
/**
* Customize available variation
*
* #param array $args
* #param WC_Product_Variable $product
* #param WC_Product_Variation $variation
*/
function customizing_available_variation( $args, $product, $variation ) {
$weight = get_post_meta( $variation->get_id(), 'custom_field', true );
// …
}
Since WooCommerce 3.x there is native Brand support now. However, Brands are not part of the Default Import/Export functionality of a Product. I found the documentation on how to add a custom column in import/export:
/**
* Add the custom column to the exporter and the exporter column menu.
*
* #param array $columns
* #return array $columns
*/
function add_export_column( $columns ) {
// column slug => column name
$columns['custom_column'] = 'Custom Column';
return $columns;
}
add_filter( 'woocommerce_product_export_column_names', 'add_export_column' );
add_filter( 'woocommerce_product_export_product_default_columns', 'add_export_column' );
/**
* Provide the data to be exported for one item in the column.
*
* #param mixed $value (default: '')
* #param WC_Product $product
* #return mixed $value - Should be in a format that can be output into a text file (string, numeric, etc).
*/
function add_export_data( $value, $product ) {
$value = $product->get_meta( 'custom_column', true, 'edit' );
return $value;
}
// Filter you want to hook into will be: 'woocommerce_product_export_product_column_{$column_slug}'.
add_filter( 'woocommerce_product_export_product_column_custom_column', 'add_export_data', 10, 2 );
Using $product->get_meta( 'brands', true, 'edit' ); did not work out. How can I add Brands to the import/export?
UPDATE:
What I did to fix this problem.. - Moved Brands to "Tags" Column - On Admin, Bulk Edit Products by tag, and mark the corresponding Column.
I've been using the Ultimate Brands plugin & thought too there must be a way of updating the custom taxonomy values via CSV. I managed to import brand names using the Woocommerce Product CSV Import Suite but have yet to find a way to export via the Woocommerce built in Exporter. Not being a developer, I thought it must be something related to the 'get_terms' function. I've tried many variations with no luck as yet. Was thinking it should look something like this, but not managed to get it to work yet:
function add_export_data() {
$product_id = $post->ID;
$value = get_terms($product_id, 'product_brand');
return $value;
}
Filter you want to hook into will be: 'woocommerce_product_export_product_column_{$column_slug}'.
So if your custom column name is product_brand, then add_filter will be like:
add_filter( 'woocommerce_product_export_product_column_product_brand', 'add_export_data', 10, 2 );
function add_export_data( $value, $product ) {
$value = $product->get_meta( 'product_brand', true, 'edit' );
return $value;
}
If your custom column name is brands, then add_filter will be like:
add_filter( 'woocommerce_product_export_product_column_brands', 'add_export_data', 10, 2 );
function add_export_data( $value, $product ) {
$value = $product->get_meta( 'brands', true, 'edit' );
return $value;
}