Time to time we change SKU in a product. But we want to keep old SKU in order tables. Woocommerce change old orders' SKU's one you update the product.
So we had below code and was working great. But after new updates it doesn't work anymore. What can we do?
add_action('woocommerce_thankyou', 'add_current_sku', 4);
function add_current_sku($order_id)
{
$order = wc_get_order($order_id);
$product = $order->get_items();
$skus = array();
global $wpdb;
foreach ($order->get_items() as $item_id => $item) {
$product = $item->get_product();
$product_id = $item->get_product_id();
if ($product->is_type('composite')) {
$skus[] = array(
"sku" => $product->sku,
"product_id" => $product_id,
);
}
}
update_post_meta($order_id, "erp_productcode", $skus);
}
Related
I need some help please. I'm making this function, but it doesn't works so far. I need to count the "Mushrooms" category products on all of orders per a specific date.!! When the ( $cont ) variable is printed.. it shows no data/value.
// Search Category products mushrromms on orders
global $woocommerce;
$posts = get_posts(array('post_type' => 'shop_order'));
$cont = 0;
foreach ($posts as $post) {
$order_id = $post->ID;
$order = new WC_Order($order_id);
$items = $order->get_items();
foreach($items as $item) {
$product_id = $item->get_product_id();
$order_date = $item->get_date_created(); //get_date_created();
if ( has_term( 'Mushrooms', 'product_cat', $product_id ) ){
$cont++;
// break;
}
}
}
Having had a look at your code, the $posts is not returning any posts. As a starting point I suggest that as you are looking at WooCommerce orders that you make use of the WooCommerce specify methods for searching the orders.
Here is your code with some suggestions and corrections with comments inline. Hopefully this will help. I have tested and I believe all you need to do now is add the date restriction criteria in the query at the start and it should work for you. I have stuck with your variable names but you may decide to tweak the code to better reflect what is now happening.
// Search Category products mushrromms on orders
//global $woocommerce;
//$posts = get_posts(array('post_type' => 'shop_order'));
// as you are searching woocommerce post why not use the designated woocommerce search method
// for reference https://github.com/woocommerce/woocommerce/wiki/wc_get_orders-and-WC_Order_Query
$args = array(
'limit' => -1,
'return' => 'ids', // this will return an array of just the ids
// later you can put your date criteria here
);
$posts = wc_get_orders( $args );
$cont = 0;
foreach ($posts as $post) {
//$order_id = $post->ID; // $post is already the ID as we returned ids from the wc_get_orders query
$order_id = $post;
$order = new WC_Order($order_id);
$items = $order->get_items();
foreach($items as $item) {
$product_id = $item->get_product_id();
$order_date = $order->get_date_created(); //get_date_created(); *** I think you meant $order not $item
if ( has_term( 'Mushrooms', 'product_cat', $product_id ) ){
$cont++;
// break;
}
}
}
A useful way of debugging this kind of situation, provided you are on a test server is to turn on debugging in the wp-config.php and then add print statements eg if you had added
error_log(print_r($posts,true));
You would have quickly discovered that it was returning an empty array. Therefore knowing where to start with finding the issue.
I sort my cart by category using this code snippet:
//order in cart
function woocommerce_before_cart_contents(){
global $woocommerce;
$cat_wisw_pros = array();
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $cart_item ) {
$product_id = $cart_item['product_id'];
$cat_ids = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'ids' ) );
foreach ( $cat_ids as $id ) {
$cat_wisw_pros[$id][$cart_item_key] = $cart_item;
}
}
ksort( $cat_wisw_pros ); // Cat ID wise sort
$grouped_cart_items = array();
foreach ( $cat_wisw_pros as $cat_id => $cart_items ) {
foreach ( $cart_items as $cart_item_key => $cart_item ) {
if( !array_key_exists( $cart_item_key, $grouped_cart_items ) )
$grouped_cart_items[$cart_item_key] = $cart_item;
}
}
$woocommerce->cart->cart_contents = $grouped_cart_items;
}
add_action( 'woocommerce_before_cart_contents', 'woocommerce_before_cart_contents' );
This works perfectly, as you can see on the picture:
Red Boxes:
The product category "Basic Products-GNC-Verkauf" is the first one, and then comes "Werbematerial/Luxusproben".
But as soon I paid, there isn't the sorted order. So the problem is, that on the invoice the sorted order vanishes. But I need, that the customer can see that the order is sorted.
How can I apply the order needs to be sorted?
The custom sort order is no longer applied when leaving the cart page because you are using woocommerce_before_cart_contents hook.
You can replace it with the woocommerce_cart_loaded_from_session hook, so the custom sort order is also applied on the order received page. Furthermore, I made some adjustments to your existing code:
The use of global $woocommerce is not necessary, as $cart is passed to the callback function
wp_get_post_terms() is replaced by get_category_ids()
So you get:
// Order in cart and order review page
function action_woocommerce_cart_loaded_from_session( $cart ) {
// Initialize
$cat_cart_items = array();
$grouped_cart_items = array();
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Get the product categories ID for this item
$cat_ids = $cart_item['data']->get_category_ids();
// Push to array
foreach ( $cat_ids as $id ) {
$cat_cart_items[$id][$cart_item_key] = $cart_item;
}
}
// Sort an array by key in ascending order
ksort( $cat_cart_items );
// Loop through cat cart items
foreach ( $cat_cart_items as $cart_items ) {
// Loop through cart items
foreach ( $cart_items as $cart_item_key => $cart_item ) {
// Checks an array for a specified key and if the key does not exist
if ( ! array_key_exists( $cart_item_key, $grouped_cart_items ) ) {
// Push to array
$grouped_cart_items[$cart_item_key] = $cart_item;
}
}
}
// Cart contents
$cart->cart_contents = $grouped_cart_items;
}
add_action( 'woocommerce_cart_loaded_from_session', 'action_woocommerce_cart_loaded_from_session', 10, 1 );
I already found a snippet to sort the checkout cart alphabetically. This works perfect but as mentioned I try to sort and group my products by category.
Is there anyone who could tweak the following snippet so it sorts the products by category?
add_action( 'woocommerce_cart_loaded_from_session', 'bbloomer_sort_cart_items_alphabetically' );
function bbloomer_sort_cart_items_alphabetically() {
global $woocommerce;
// READ CART ITEMS
$products_in_cart = array();
foreach ( $woocommerce->cart->cart_contents as $key => $item ) {
$products_in_cart[ $key ] = $item['data']->get_title();
}
// SORT CART ITEMS
natsort( $products_in_cart );
// ASSIGN SORTED ITEMS TO CART
$cart_contents = array();
foreach ( $products_in_cart as $cart_key => $product_title ) {
$cart_contents[ $cart_key ] = $woocommerce->cart->cart_contents[ $cart_key ];
}
$woocommerce->cart->cart_contents = $cart_contents;
}
In order to grouped cart items by categories, add follows code snippet -
function woocommerce_before_cart_contents(){
global $woocommerce;
$cat_wisw_pros = array();
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $cart_item ) {
$product_id = $cart_item['product_id'];
$cat_ids = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'ids' ) );
foreach ( $cat_ids as $id ) {
$cat_wisw_pros[$id][$cart_item_key] = $cart_item;
}
}
ksort( $cat_wisw_pros ); // Cat ID wise sort
$grouped_cart_items = array();
foreach ( $cat_wisw_pros as $cat_id => $cart_items ) {
foreach ( $cart_items as $cart_item_key => $cart_item ) {
if( !array_key_exists( $cart_item_key, $grouped_cart_items ) )
$grouped_cart_items[$cart_item_key] = $cart_item;
}
}
$woocommerce->cart->cart_contents = $grouped_cart_items;
}
add_action( 'woocommerce_before_cart_contents', 'woocommerce_before_cart_contents' );
You should be able to access the category ids with the method get_category_ids() as defined in the class WC_Product
$item['data']->get_category_ids()
but this gives you back an array, so you need to handle getting the id, e.g.
$ids = $item['data']->get_category_ids();
$id = $ids[ 0 ];
and transforming to a string, e.g.
$term_obj = get_term( $id, 'product_cat' );
$name = $term_obj->name;
you could then do
$products_in_cart[ $key ] = $name;
and by the same logic used in the code in your question sort by category.
There are several things to consider though, this does not handle items being in multiple categories, it just gets the first by using index 0. Additionally, this has no extra logic of sorting, if there are multiple products in the same category.
Please note, this is untested and merely an idea of an approach of how this could be handled.
Using a woocommerce hook to retrieve the sales information after the payment has been received. I can find the product name, the fact that it is a subscription, but I need to retrieve the subscription variation that was selected by the customer. I can get a list OF the variations, but not the exact one selected.
Everything works EXCEPT the ability to discover what variation the customer choose,
I even tried getting the meta data, only to not be able to gain access to it.
$meta_data = $product->get_formatted_meta_data('_', true);
foreach( $items as $item_id => $product )
{
$ProductName = $product->get_name(); // readable name of
product
$ProductId = $product->get_product_id(); // woocommerce id of
product
$PaymentAmount = $product->get_total(); // Get Payment of subscription item,
$ProductIndex = wc_get_product($ProductId);
if(! WC_Subscriptions_Product::is_subscription( $ProductIndex ) )
continue;
if(!$product->is_type( 'simple' ))
{
// THIS CRASHES WITH INTERNAL SERVICE ERROR
$variation_attributes = $product->get_variation_attributes();
foreach($variation_attributes as $attribute_taxonomy => $term_slug)
{
$taxonomy = str_replace('attribute_', '', $attribute_taxonomy );
$attribute_name = get_taxonomy( $taxonomy )->labels->singular_name;
$BusinessSpeciality = get_term_by( 'slug', $term_slug, $taxonomy )->name;
}
}
Found the solution..simple:
foreach( $items as $item_id => $product )
{
if(!$product->is_type( 'simple' ) && $product->is_virtual())
{
$variation_id = $product['variation_id'];
$variation = new WC_Product_Variation($variation_id);
$BusinessSpeciality = current($variation->get_variation_attributes());
}
else
$BusinessSpeciality = 'Default';
}`
I have the function below which works to change the role of a user when they buy certain products, but instead of listing out specific product IDs, I'd like to just use the category name or id of those products. That way, if we add a new product in that category, I don't have to remember to add it to this function. This function is specific to a certain category, so it doesn't matter if people have other products from other categories in the order.
function lgbk_add_member( $order_id ) {
$order = new WC_Order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$product_variation_id = $item['variation_id'];
if ( $order->user_id > 0 && $product_id == '7' ) {
update_user_meta( $order->user_id, 'paying_customer', 1 );
$user = new WP_User( $order->user_id );
// Remove role
$user->remove_role( 'expired' );
// Add role
$user->add_role( 'customer' );
}
}
}
add_action( 'woocommerce_order_status_completed', 'lgbk_add_member' );
You have to use wp_get_post_terms to get category id of any product like this :
$term_list = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));
I am just fetching id's of categories assigned to this particular product, you can fetch name also.
You can get product category name using this function -
function get_product_category_name_by_id( $category_id ) {
$term = get_term_by( 'id', $category_id, 'product_cat', 'ARRAY_A' );
return $term['name'];
}
$product_category = get_product_category_name_by_id( $your_category_id );
Thanks!