__( 'Odoo URL (e.g. https://odoo.example.com)', 'woodoo' ), 'woodoo_odoo_db' => __( 'Database Name', 'woodoo' ), 'woodoo_odoo_username' => __( 'Username / Login', 'woodoo' ), 'woodoo_odoo_api_key' => __( 'API Key', 'woodoo' ), ]; foreach ( $fields as $key => $label ) { register_setting( 'woodoo_settings', $key, [ 'sanitize_callback' => 'sanitize_text_field' ] ); } // Meeting settings $meeting_fields = [ 'woodoo_meeting_duration' => 30, // minutes 'woodoo_available_days' => [ 1, 2, 3, 4, 5 ], // Mon-Fri 'woodoo_available_from' => '09:00', 'woodoo_available_to' => '17:00', 'woodoo_meeting_title_prefix'=> 'Meeting via WooDoo', ]; foreach ( $meeting_fields as $key => $default ) { register_setting( 'woodoo_settings', $key ); } // Order sync toggle register_setting( 'woodoo_settings', 'woodoo_sync_orders', [ 'sanitize_callback' => 'rest_sanitize_boolean' ] ); } public static function enqueue_admin_assets( string $hook ): void { if ( strpos( $hook, 'woodoo-settings' ) === false && $hook !== 'user-edit.php' && $hook !== 'profile.php' ) { return; } wp_enqueue_style( 'woodoo-admin', WOODOO_URL . 'assets/css/woodoo-admin.css', [], WOODOO_VERSION ); wp_enqueue_script( 'woodoo-admin', WOODOO_URL . 'assets/js/woodoo-admin.js', [ 'jquery' ], WOODOO_VERSION, true ); wp_localize_script( 'woodoo-admin', 'WooDooAdmin', [ 'nonce' => wp_create_nonce( 'woodoo_admin' ), 'ajax_url' => admin_url( 'admin-ajax.php' ), 'i18n' => [ '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' ), ], ] ); } // ── Settings Page HTML ──────────────────────────────────────────────── public static function render_settings_page(): void { if ( ! current_user_can( 'manage_woocommerce' ) ) { wp_die( esc_html__( 'Access denied.', 'woodoo' ) ); } $days_map = [ 1 => __( 'Monday', 'woodoo' ), 2 => __( 'Tuesday', 'woodoo' ), 3 => __( 'Wednesday', 'woodoo' ), 4 => __( 'Thursday', 'woodoo' ), 5 => __( 'Friday', 'woodoo' ), 6 => __( 'Saturday', 'woodoo' ), 7 => __( 'Sunday', 'woodoo' ), ]; $saved_days = (array) get_option( 'woodoo_available_days', [ 1, 2, 3, 4, 5 ] ); ?>

ID, 'woodoo_odoo_partner_id', true ); $partner_name = get_user_meta( $user->ID, 'woodoo_odoo_partner_name', true ); ?>

ID, 'woodoo_so_count', true ); if ( $odoo_so_count ) : ?>


0 ) { update_user_meta( $user_id, 'woodoo_odoo_partner_id', $partner_id ); // Resolve name from Odoo $api = woodoo_api(); if ( $api ) { $partners = $api->read( 'res.partner', [ $partner_id ], [ 'name', 'email' ] ); if ( ! empty( $partners[0]['name'] ) ) { update_user_meta( $user_id, 'woodoo_odoo_partner_name', sanitize_text_field( $partners[0]['name'] ) ); } } } else { delete_user_meta( $user_id, 'woodoo_odoo_partner_id' ); delete_user_meta( $user_id, 'woodoo_odoo_partner_name' ); } } // ── Users List Column ───────────────────────────────────────────────── public static function add_users_column( array $columns ): array { $columns['woodoo_odoo'] = __( 'Odoo Partner', 'woodoo' ); return $columns; } public static function render_users_column( string $value, string $column, int $user_id ): string { if ( $column !== 'woodoo_odoo' ) return $value; $partner_id = get_user_meta( $user_id, 'woodoo_odoo_partner_id', true ); $partner_name = get_user_meta( $user_id, 'woodoo_odoo_partner_name', true ); if ( $partner_id ) { return '' . esc_html( $partner_name ?: "#$partner_id" ) . ''; } return ''; } // ── AJAX Handlers ───────────────────────────────────────────────────── public static function ajax_test_connection(): void { check_ajax_referer( 'woodoo_admin', 'nonce' ); if ( ! current_user_can( 'manage_woocommerce' ) ) wp_send_json_error( 'Forbidden', 403 ); $api = woodoo_api(); if ( ! $api ) { wp_send_json_error( 'Credentials not saved yet. Save settings first.' ); } wp_send_json_success( $api->test_connection() ); } public static function ajax_search_partners(): 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'] ?? '' ) ); $api = woodoo_api(); if ( ! $api || empty( $q ) ) wp_send_json_success( [] ); $results = $api->search_read( 'res.partner', [ '|', [ 'name', 'ilike', $q ], [ 'email', 'ilike', $q ] ], [ 'id', 'name', 'email', 'is_company' ], 10 ); wp_send_json_success( $results ); } public static function ajax_link_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 ); $partner_id = absint( $_POST['partner_id'] ?? 0 ); if ( ! $user_id || ! $partner_id ) wp_send_json_error( 'Invalid IDs' ); $api = woodoo_api(); if ( ! $api ) wp_send_json_error( 'API not configured' ); $partners = $api->read( 'res.partner', [ $partner_id ], [ 'name', 'email' ] ); if ( empty( $partners ) ) wp_send_json_error( 'Partner not found in Odoo' ); update_user_meta( $user_id, 'woodoo_odoo_partner_id', $partner_id ); update_user_meta( $user_id, 'woodoo_odoo_partner_name', sanitize_text_field( $partners[0]['name'] ) ); wp_send_json_success( [ 'partner_id' => $partner_id, '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 ); } }