skip to Main Content

I’m working on an e-commerce project. When a customer purchases a product, they are assigned a Customer Code based on their first name, last name and sequential numbers. It’s used by the accounting software.

Here’s my code:

add_action( 'show_user_profile', 'ipx_user_profile_fields' );
add_action( 'edit_user_profile', 'ipx_user_profile_fields' );

function ipx_user_profile_fields( $user ) { ?>
    <h3><?php _e("IPX", "blank"); ?></h3>

    <table class="form-table">
    <tr>
        <th><label for="ipx_customer_code"><?php _e("Customer Code"); ?></label></th>
        <td>
            <input type="text" name="ipx_customer_code" id="ipx_customer_code" value="<?php echo esc_attr( get_the_author_meta( 'ipx_customer_code', $user->ID ) ); ?>" class="regular-text" /><br />
            <span class="description"><?php _e("This field should contain only the IPX Customer Code."); ?></span>
        </td>
    </tr>
    </table>
<?php }

add_action( 'personal_options_update', 'save_ipx_user_profile_fields' );
add_action( 'edit_user_profile_update', 'save_ipx_user_profile_fields' );

function save_ipx_user_profile_fields( $user_id ) {
    if ( !current_user_can( 'edit_user', $user_id ) ) { 
        return false; 
    }
    update_user_meta( $user_id, 'ipx_customer_code', $_POST['ipx_customer_code'] );
}

/**
 * Generate customer code based on user's first name, last name and a sequential number
 */
function generate_customer_code($user_id) {
    $user = get_userdata($user_id);
    $first_name = $user->first_name;
    $last_name = $user->last_name;

    // Get the current sequential number for the customer code
    $sequential_number = get_user_meta($user_id, 'sequential_customer_code', true);
    if (!$sequential_number) {
        $sequential_number = 0;
    }

    // Loop until a unique customer code is generated
    do {
        $sequential_number++;
        // Generate the customer code
        $customer_code = strtoupper(substr($first_name, 0, 4) . substr($last_name, 0, 4) . sprintf('%02d', $sequential_number));
        // Check if the customer code already exists
        $user_query = new WP_User_Query(array(
            'meta_key' => 'ipx_customer_code',
            'meta_value' => $customer_code
        ));
    } while (!empty($user_query->results));

    // Save the customer code and sequential number as separate custom fields
    update_user_meta($user_id, 'ipx_customer_code', $customer_code);
    update_user_meta($user_id, 'sequential_customer_code', $sequential_number);
}
add_action('user_register', 'generate_customer_code');

It checks to see if the Customer Code is already used and moves onto the next (sequentially) if it is.

I’ve been testing this out and come up against a problem. It only works if the customer creates an account. My client is adamant that Guest access should remain switched on, which means that a Customer Code is never generated.

Is there a way to store this information in the wp_wc_customer_lookup table instead? That records all customers, irrespective of whether they’ve registered or not. I think my client would still want to see the Customer Code somewhere physically (on the WooCommerce Customers tab?) but it needs to be for every customer, not just registered customers.

Any thoughts would be appreciated. And apologies in advance for any dodgy coding – my PHP is rough, but I’d rather attempt it than not.

2

Answers


  1. Here, the idea is to register Guest users when they make a purchase on your store.

    • First, we add to WordPress a "guest" user role (the first function).
    • Then, once the order is processed (meaning that the order is created and saved to the database, just before payment), we hook a function where we register the user as "guest" using the WordPress function wp_insert_user() that WooCommerce uses too.

    Now as your last function that generates a "Customer Code" is hooked in user_register WordPress hook that is triggered precisely by wp_insert_user(), so that function will be executed, and that solves your problem.

    The code (untested):

    // Add "guest" user role
    add_action( 'init', 'add_role_guest' );
    function add_role_guest() {
        add_role(
            'guest',
            __( 'Guest', 'woocommerce' ),
            array( 'read' => true )
        );
    }
    
    // Registering unregistered Guest users
    add_action( 'woocommerce_checkout_order_processed', 'process_checkout_guest', 10, 3 );
    function process_checkout_guest( $order_id, $posted_data, $order ) {
        $user_id = $order->get_user_id(); // Get user Id (for guest the value is 0)
        $b_email = $order->get_billing_email(); // Get email from order
    
       // Only Guest
        if ( ! $user_id ) {
            // check with th email if WP_User exist
            $user = get_user_by( 'email', $b_email );
    
            // WP_User don't exist
            if ( $b_email && ! $user ) {
                // Generating the username
                $username = wc_create_new_customer_username( $b_email, array(
                    'first_name' => $order->get_billing_first_name(),
                    'last_name' => $order->get_billing_last_name(),
                ) );
    
                // Creating user
                $user_id = wp_insert_user( array(
                    'user_login' => $username,
                    'user_pass'  => wp_generate_password(),
                    "first_name" => $order->get_billing_first_name(),
                    'last_name'  => $order->get_billing_last_name(),
                    'user_email' => sanitize_email($b_email),
                    'role'       => 'guest', // Custom user role
                ) );
                // For testing
                if ( is_wp_error( $user_id ) ) {
                    error_log( print_r($user_id, true) );
                }
            } 
        }
    }
    

    It should work.

    This required testing, to be sure that there are no bad interactions with WooCommerce.

    I think that it’s the best and simplest way.

    Login or Signup to reply.
  2. I noticed that the issue may lie in the database query within the do-while loop. The query checks for the existence of a customer code in the ipx_customer_code meta_key column, but the table being queried is $wpdb->prefix . ‘woocommerce_customer_lookup’.

    To resolve this issue, please make sure that you have the correct table name for the woocommerce_customer_lookup table in your database. You can check the database prefix by examining the WordPress configuration file (wp-config.php) or by verifying the table names in your WordPress database directly.

    Once you have determined the correct table name, replace $wpdb->prefix . ‘woocommerce_customer_lookup’ in the code with the appropriate table name. This should ensure that the query is executed against the correct table where the ipx_customer_code column exists.

    Here’s an updated version of the code snippet with a placeholder for the correct table name:

    add_action('woocommerce_checkout_update_customer', 'generate_customer_code');
    
    /**
     * Generate customer code based on user's first name, last name, and a sequential number
     *
     * @param int $customer_id The customer ID
     */
    function generate_customer_code($customer_id) {
        global $wpdb;
    
        $customer_data = wc_get_customer($customer_id);
        $first_name = $customer_data->get_first_name();
        $last_name = $customer_data->get_last_name();
    
        // Get the current sequential number for the customer code
        $sequential_number = get_user_meta($customer_id, 'sequential_customer_code', true);
        if (!$sequential_number) {
            $sequential_number = 0;
        }
    
        // Loop until a unique customer code is generated
        do {
            $sequential_number++;
            // Generate the customer code
            $customer_code = strtoupper(substr($first_name, 0, 4) . substr($last_name, 0, 4) . sprintf('%02d', $sequential_number));
            // Check if the customer code already exists
            $existing_customer = $wpdb->get_var(
                $wpdb->prepare(
                    "
                    SELECT customer_id
                    FROM {replace_with_table_name}
                    WHERE customer_id <> %d AND meta_key = 'ipx_customer_code' AND meta_value = %s
                    ",
                    $customer_id,
                    $customer_code
                )
            );
        } while ($existing_customer);
    
        // Save the customer code and sequential number as separate custom fields
        update_user_meta($customer_id, 'ipx_customer_code', $customer_code);
        update_user_meta($customer_id, 'sequential_customer_code', $sequential_number);
    
        // Update the customer lookup table with the customer code
        $wpdb->update(
            '{replace_with_table_name}',
            array('meta_value' => $customer_code),
            array('customer_id' => $customer_id, 'meta_key' => 'ipx_customer_code')
        );
    }
    

    Remember to replace ‘{replace_with_table_name}’ with the correct table name for the ‘woocommerce_customer_lookup’ table in your WordPress database. After making this change, please test the code again to see if it resolves the issue and correctly saves the ‘ipx_customer_code’ entry in the database.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search