user6580560
user6580560

Reputation:

WooCommerce: How can I share an order between two customers?

a week ago I've started to build a WooCommerce store which should have the option to share orders between two customers. Here is a little diagram I've made for you so you can understand how it should be (Please take a look at it):

enter image description here

So here is what I did step for step


User B clicks a button -> (Save second user id to the order):

$related_order = $_POST['related_order'];
$current_user = wp_get_current_user();
$userID = $current_user->ID;
update_post_meta($related_order, 'second_user_id', $userID);

User B clicks another button -> (Remove second user id from the order)

$related_order = $_POST['related_order'];
$current_user = wp_get_current_user();
$user_id = $current_user->ID;
delete_post_meta($related_order , 'second_user_id');

These two steps (show and hide the order for user B) are working fine - I've tested it. The field gets set and unset.


Now it's getting worse:

I've searched a lot and asked some people to find the function in WooCommerce which gets all orders for a customer. After I found it I've tried to change it so that the second_user_id field gets checked to. I simply thought that I can show the order from customer A to B this way:

function woocommerce_account_orders( $current_page ) {
    $current_page    = empty( $current_page ) ? 1 : absint( $current_page );
    $customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array(
        'customer' => get_current_user_id(),
        'second_user_id' => get_current_user_id(),
        'page'     => $current_page,
        'paginate' => true,
    ) ) );

    wc_get_template(
        'myaccount/orders.php',
        array(
            'current_page'    => absint( $current_page ),
            'customer_orders' => $customer_orders,
            'has_orders'      => 0 < $customer_orders->total,
        )
    );
}

The method is located in: https://docs.woocommerce.com/wc-apidocs/source-function-woocommerce_account_orders.html#2465-2486


As you can see I've tried to add the second_user_id to the query which returns the orders for a customer. This is my custom field saved in each order:

[5] => WC_Meta_Data Object (
     [current_data:protected] => Array (
          [id] => 3477
          [key] => second_user_id
          [value] => 2
)

After that did not worked I've got help from a friendly guy which told me, that this can't work the way I did it. There are permission which must be given to the user B to view the order from A and a lot of other stuff... So is there someone who can help me with this part? What is wrong with my implementation and how can I change the functionality the way I need it?

Upvotes: 0

Views: 896

Answers (1)

kashalo
kashalo

Reputation: 3562

if we take look at the responsbile function which WooCommerce use to query the customer you will WooCommerceselect all orders which related to the user based on the user id.

Functions source code:

function woocommerce_account_orders( $current_page ) {
    $current_page    = empty( $current_page ) ? 1 : absint( $current_page );
    $customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array(
        'customer' => get_current_user_id(),
        'page'     => $current_page,
        'paginate' => true,
    ) ) );

    wc_get_template(
        'myaccount/orders.php',
        array(
            'current_page'    => absint( $current_page ),
            'customer_orders' => $customer_orders,
            'has_orders'      => 0 < $customer_orders->total,
        )
    );
}
}

If you want to alter this query and add specific order id's which is not belong to this user beside the default orders we need to do some sort of hack to this query and the possible option i can think of now is by using post__in instead of getting the orders by customer id.

we are going to use the woocommerce_my_account_my_orders_query filter to alter the query.

i will assume the additional orders for that user is stored in wp_usermeta table

The Solution will be:

add_filter( 'woocommerce_my_account_my_orders_query',  'modify_my_order_query'  , 20, 1 );

function modify_my_order_query( $q ) {
    global $wpdb;
    $current_user_id = get_current_user_id();
    //Check if the user have addtional orders
    $secondary_post_ids = get_user_meta( $current_user_id, 'additional_orders', false );
    if ( ! empty( $secondary_post_ids ) ) {

        // Get All Orders ID for the main customers
        $prepare_query = $wpdb->prepare(
            " SELECT post_id  FROM {$wpdb->postmeta}
    WHERE meta_key LIKE %s and meta_value LIKE %d ",
            '_customer_user',
            $current_user_id
        );
        $results       = $wpdb->get_results( $prepare_query, ARRAY_A );
        $main_post_ids = wp_list_pluck( $results, 'post_id' );

        // Merge All Orders IDs

        $all_posts_ids = ( isset( $secondary_post_ids[0] ) ) ? array_merge( $main_post_ids, $secondary_post_ids[0] ) : $main_post_ids;
        //Modify the my Order Query to include all orders ID including the additional ones
        unset( $q['customer'] );
        $q['post__in'] = $all_posts_ids;
    }

    return $q;
}

you will see in the above solution first we check if the current user have additional order if yes then we select all his default orders id and merge the array with his additional order is and then we modified the query so we can get all those orders.

Now the only things left is to allow the user to see his additional orders and to do so we need to use user_has_cap hook.

 add_filter( 'user_has_cap',   'give_permissions'  , 10, 3 );

 function give_permissions( $allcaps, $cap, $args ) {

    if ( isset( $cap[0] ) && $cap[0] == 'view_order' ) {
        $get_additional_ids = get_user_meta( get_current_user_id(), 'additional_orders', false );
        if ( isset( $get_additional_ids[0] ) && in_array( $args[2], $get_additional_ids[0] ) ) {
            $allcaps[ $cap[0] ] = true;
        }
    }
    return ( $allcaps );
}

i believe this solution will achieve your target goal.

Upvotes: 1

Related Questions