fix: customer search & linking fully implemented

- Add ajax_search_wc_customers() – searches user_login, user_email,
  display_name AND first_name/last_name meta so any query returns hits
- Add ajax_unlink_customer() to remove an existing Odoo link
- Replace placeholder Customers tab with two-panel UI:
  Step 1 search WC customers → Step 2 search Odoo partners independently
  (WC email and Odoo email do not need to match)
- Results table shows current link status; inline Link/Unlink actions
  update the row in-place without page reload
- Admin JS fully wired: both search inputs respond to Enter key and button
- Add two-panel layout CSS and results table styles

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Malin
2026-04-01 17:18:01 +02:00
parent 68c1ff4455
commit 38d1352e9a
3 changed files with 426 additions and 73 deletions

View File

@@ -21,7 +21,9 @@ class WooDoo_Admin {
// AJAX handlers (admin only)
add_action( 'wp_ajax_woodoo_test_connection', [ __CLASS__, 'ajax_test_connection' ] );
add_action( 'wp_ajax_woodoo_search_partners', [ __CLASS__, 'ajax_search_partners' ] );
add_action( 'wp_ajax_woodoo_search_wc_customers',[ __CLASS__, 'ajax_search_wc_customers' ] );
add_action( 'wp_ajax_woodoo_link_customer', [ __CLASS__, 'ajax_link_customer' ] );
add_action( 'wp_ajax_woodoo_unlink_customer', [ __CLASS__, 'ajax_unlink_customer' ] );
// WC customer list column
add_filter( 'manage_users_columns', [ __CLASS__, 'add_users_column' ] );
@@ -91,10 +93,17 @@ class WooDoo_Admin {
'nonce' => wp_create_nonce( 'woodoo_admin' ),
'ajax_url' => admin_url( 'admin-ajax.php' ),
'i18n' => [
'testing' => __( 'Testing…', 'woodoo' ),
'searching' => __( 'Searching…', 'woodoo' ),
'link_done' => __( 'Linked!', 'woodoo' ),
'error' => __( 'Error. Check console.', 'woodoo' ),
'testing' => __( 'Testing…', 'woodoo' ),
'searching' => __( 'Searching…', 'woodoo' ),
'no_wc_customers' => __( 'No customers found.', 'woodoo' ),
'no_odoo_partners' => __( 'No Odoo partners found.', 'woodoo' ),
'link_done' => __( 'Linked!', 'woodoo' ),
'unlink_confirm' => __( 'Remove the Odoo link for this customer?', 'woodoo' ),
'unlinked' => __( 'Unlinked', 'woodoo' ),
'error' => __( 'Error. Check console.', 'woodoo' ),
'search_odoo' => __( 'Search Odoo partners…', 'woodoo' ),
'linked_to' => __( 'Linked to', 'woodoo' ),
'not_linked' => __( 'Not linked', 'woodoo' ),
],
] );
}
@@ -230,12 +239,35 @@ class WooDoo_Admin {
<!-- Customer Linking Tab -->
<div id="tab-customers" class="woodoo-tab" style="display:none;">
<h2><?php esc_html_e( 'Customer Linking', 'woodoo' ); ?></h2>
<p><?php esc_html_e( 'Link WooCommerce customers to their Odoo partner record. You can also edit this from each user\'s profile page.', 'woodoo' ); ?></p>
<p><?php esc_html_e( 'Search a WooCommerce customer, then search and pick their matching Odoo partner. Emails do not need to match.', 'woodoo' ); ?></p>
<div class="woodoo-customer-linker">
<label><?php esc_html_e( 'Search WooCommerce Customer:', 'woodoo' ); ?></label>
<input type="text" id="woo-customer-search" class="regular-text" placeholder="<?php esc_attr_e( 'Customer name or email…', 'woodoo' ); ?>">
<div id="woo-customer-results"></div>
<div class="woodoo-linker-panel">
<div class="woodoo-linker-col">
<h3><?php esc_html_e( '1. Find WooCommerce Customer', 'woodoo' ); ?></h3>
<div class="woodoo-search-row">
<input type="text" id="woo-customer-search"
class="regular-text"
placeholder="<?php esc_attr_e( 'Name or email…', 'woodoo' ); ?>">
<button type="button" id="woo-customer-search-btn" class="button button-secondary">
<?php esc_html_e( 'Search', 'woodoo' ); ?>
</button>
</div>
<div id="woo-customer-results" class="woodoo-results-list"></div>
</div>
<div class="woodoo-linker-col" id="woodoo-odoo-col" style="display:none;">
<h3><?php esc_html_e( '2. Find Odoo Partner', 'woodoo' ); ?></h3>
<p id="woodoo-linking-for" class="woodoo-linking-for"></p>
<div class="woodoo-search-row">
<input type="text" id="woodoo-odoo-partner-search"
class="regular-text"
placeholder="<?php esc_attr_e( 'Name or email…', 'woodoo' ); ?>">
<button type="button" id="woodoo-odoo-partner-search-btn" class="button button-secondary">
<?php esc_html_e( 'Search', 'woodoo' ); ?>
</button>
</div>
<div id="woodoo-odoo-partner-results" class="woodoo-results-list"></div>
</div>
</div>
</div>
@@ -399,4 +431,81 @@ class WooDoo_Admin {
'partner_name' => $partners[0]['name'],
] );
}
public static function ajax_unlink_customer(): void {
check_ajax_referer( 'woodoo_admin', 'nonce' );
if ( ! current_user_can( 'edit_users' ) ) wp_send_json_error( 'Forbidden', 403 );
$user_id = absint( $_POST['user_id'] ?? 0 );
if ( ! $user_id ) wp_send_json_error( 'Invalid user ID' );
delete_user_meta( $user_id, 'woodoo_odoo_partner_id' );
delete_user_meta( $user_id, 'woodoo_odoo_partner_name' );
wp_send_json_success( [ 'user_id' => $user_id ] );
}
/**
* Search WooCommerce customers by name or email.
* Searches user_login, user_email, display_name in the users table,
* AND first_name / last_name in user meta — so the email in WC doesn't
* need to match Odoo at all.
*/
public static function ajax_search_wc_customers(): void {
check_ajax_referer( 'woodoo_admin', 'nonce' );
if ( ! current_user_can( 'edit_users' ) ) wp_send_json_error( 'Forbidden', 403 );
$q = sanitize_text_field( wp_unslash( $_POST['query'] ?? '' ) );
if ( strlen( $q ) < 2 ) wp_send_json_error( 'Query too short' );
// Search main user table columns
$query1 = new WP_User_Query( [
'search' => '*' . $q . '*',
'search_columns' => [ 'user_login', 'user_email', 'display_name' ],
'number' => 20,
'fields' => 'all',
] );
// Search first_name / last_name meta fields
$query2 = new WP_User_Query( [
'number' => 20,
'fields' => 'all',
'meta_query' => [
'relation' => 'OR',
[ 'key' => 'first_name', 'value' => $q, 'compare' => 'LIKE' ],
[ 'key' => 'last_name', 'value' => $q, 'compare' => 'LIKE' ],
],
] );
// Merge and deduplicate
$all = array_merge( $query1->get_results(), $query2->get_results() );
$seen = [];
$users = [];
foreach ( $all as $user ) {
if ( isset( $seen[ $user->ID ] ) ) continue;
$seen[ $user->ID ] = true;
$users[] = $user;
}
if ( empty( $users ) ) {
wp_send_json_success( [] );
}
$results = [];
foreach ( $users as $user ) {
$partner_id = (int) get_user_meta( $user->ID, 'woodoo_odoo_partner_id', true );
$partner_name = get_user_meta( $user->ID, 'woodoo_odoo_partner_name', true );
$results[] = [
'id' => $user->ID,
'display_name' => $user->display_name,
'email' => $user->user_email,
'partner_id' => $partner_id ?: null,
'partner_name' => $partner_name ?: null,
'edit_url' => esc_url( get_edit_user_link( $user->ID ) ),
];
}
wp_send_json_success( $results );
}
}