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.
To include the customer code on an order, I've used the following the code:
add_action( 'woocommerce_checkout_update_order_meta', 'include_customer_code_on_order', 10, 2 );
function include_customer_code_on_order( $order_id, $posted_data ) {
$order = wc_get_order( $order_id );
$user_id = $order->get_user_id();
if ( $user_id ) {
$customer_code = get_user_meta( $user_id, 'ipx_customer_code', true );
if ( $customer_code ) {
$order->update_meta_data( 'ipx_customer_code', $customer_code );
$order->save();
}
}
}
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.
Here, the idea is to register Guest users when they make a purchase on your store.
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.