diff --git a/admin/class-informatiq-sp-admin.php b/admin/class-informatiq-sp-admin.php
index 062b74e8..fc4e8f78 100644
--- a/admin/class-informatiq-sp-admin.php
+++ b/admin/class-informatiq-sp-admin.php
@@ -51,6 +51,7 @@ class Informatiq_SP_Admin {
add_action( 'wp_ajax_informatiq_sp_manual_sync', array( $this, 'handle_manual_sync' ) );
add_action( 'wp_ajax_informatiq_sp_test_connection', array( $this, 'handle_test_connection' ) );
add_action( 'wp_ajax_informatiq_sp_revoke_auth', array( $this, 'handle_revoke_auth' ) );
+ add_action( 'wp_ajax_informatiq_sp_compare_products', array( $this, 'handle_compare_products' ) );
// Enqueue admin assets.
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
@@ -333,6 +334,10 @@ class Informatiq_SP_Admin {
+ render_product_comparison(); ?>
+
+
+
render_logs_section(); ?>
@@ -575,6 +580,50 @@ class Informatiq_SP_Admin {
+
+ __( 'Authorization revoked.', 'informatiq-smart-pricing' ) ) );
}
+ /**
+ * Handle product comparison AJAX request.
+ */
+ public function handle_compare_products() {
+ check_ajax_referer( 'informatiq_sp_admin', 'nonce' );
+
+ if ( ! current_user_can( 'manage_woocommerce' ) ) {
+ wp_send_json_error( array( 'message' => __( 'Insufficient permissions', 'informatiq-smart-pricing' ) ) );
+ }
+
+ $merchant_id = get_option( 'informatiq_sp_merchant_id' );
+ $client_id = get_option( 'informatiq_sp_client_id' );
+ $client_secret = get_option( 'informatiq_sp_client_secret' );
+ $refresh_token = get_option( 'informatiq_sp_refresh_token' );
+
+ if ( empty( $merchant_id ) || empty( $refresh_token ) ) {
+ wp_send_json_error( array( 'message' => __( 'Please configure settings and authorize first.', 'informatiq-smart-pricing' ) ) );
+ }
+
+ try {
+ $google_api = new Informatiq_SP_Google_API(
+ $merchant_id,
+ $client_id,
+ $client_secret,
+ $refresh_token,
+ $this->logger
+ );
+
+ // Get all Google products indexed by various identifiers.
+ $google_products_raw = $google_api->get_all_products();
+ $google_products = array();
+
+ foreach ( $google_products_raw as $gp ) {
+ // Index by offerId.
+ if ( ! empty( $gp['offerId'] ) ) {
+ $google_products['offer_' . $gp['offerId']] = $gp;
+ }
+ // Index by gtin.
+ if ( ! empty( $gp['gtin'] ) ) {
+ $google_products['gtin_' . $gp['gtin']] = $gp;
+ }
+ }
+
+ // Get WooCommerce in-stock products (limit to 50 for performance).
+ $wc_products = wc_get_products( array(
+ 'status' => 'publish',
+ 'stock_status' => 'instock',
+ 'limit' => 50,
+ 'return' => 'objects',
+ 'type' => array( 'simple', 'variable' ),
+ ) );
+
+ $comparison = array();
+
+ foreach ( $wc_products as $product ) {
+ $sku = $product->get_sku();
+ if ( empty( $sku ) ) {
+ continue;
+ }
+
+ // Get local price (sale price priority, then regular).
+ $sale_price = $product->get_sale_price();
+ $regular_price = $product->get_regular_price();
+ $local_price = ! empty( $sale_price ) ? $sale_price : $regular_price;
+ $price_type = ! empty( $sale_price ) ? 'sale' : 'regular';
+
+ // Try to find matching Google product.
+ $google_product = null;
+ $match_type = '';
+
+ // Try offerId match.
+ if ( isset( $google_products['offer_' . $sku] ) ) {
+ $google_product = $google_products['offer_' . $sku];
+ $match_type = 'offerId';
+ }
+ // Try GTIN match (when SKU is a barcode).
+ elseif ( isset( $google_products['gtin_' . $sku] ) ) {
+ $google_product = $google_products['gtin_' . $sku];
+ $match_type = 'gtin';
+ }
+
+ // Get Google price.
+ $google_price = null;
+ if ( $google_product ) {
+ if ( isset( $google_product['price']['amountMicros'] ) ) {
+ $google_price = (float) $google_product['price']['amountMicros'] / 1000000;
+ }
+ }
+
+ $comparison[] = array(
+ 'id' => $product->get_id(),
+ 'name' => $product->get_name(),
+ 'sku' => $sku,
+ 'local_price' => $local_price ? (float) $local_price : null,
+ 'price_type' => $price_type,
+ 'google_price' => $google_price,
+ 'match_type' => $match_type,
+ 'found' => ! empty( $google_product ),
+ 'google_offer' => $google_product ? ( $google_product['offerId'] ?? '' ) : '',
+ );
+ }
+
+ wp_send_json_success( array(
+ 'products' => $comparison,
+ 'google_count' => count( $google_products_raw ),
+ 'wc_count' => count( $wc_products ),
+ 'currency' => get_woocommerce_currency_symbol(),
+ ) );
+
+ } catch ( Exception $e ) {
+ wp_send_json_error( array( 'message' => $e->getMessage() ) );
+ }
+ }
+
/**
* Enqueue admin assets.
*
diff --git a/assets/js/admin.js b/assets/js/admin.js
index 26e4580d..24884022 100644
--- a/assets/js/admin.js
+++ b/assets/js/admin.js
@@ -20,6 +20,7 @@
$('#informatiq-sp-manual-sync').on('click', this.handleManualSync);
$('#informatiq-sp-test-connection').on('click', this.handleTestConnection);
$('#informatiq-sp-revoke-auth').on('click', this.handleRevokeAuth);
+ $('#informatiq-sp-compare-products').on('click', this.handleCompareProducts);
},
/**
@@ -179,6 +180,82 @@
$button.prop('disabled', false).text('Revoke Authorization');
}
});
+ },
+
+ /**
+ * Handle compare products button click
+ */
+ handleCompareProducts: function(e) {
+ e.preventDefault();
+
+ var $button = $(this);
+ var $spinner = $button.next('.spinner');
+ var $results = $('#informatiq-sp-comparison-results');
+ var $tbody = $('#informatiq-sp-comparison-tbody');
+
+ // Disable button and show spinner
+ $button.prop('disabled', true);
+ $spinner.addClass('is-active');
+
+ // Make AJAX request
+ $.ajax({
+ url: informatiqSP.ajaxUrl,
+ type: 'POST',
+ data: {
+ action: 'informatiq_sp_compare_products',
+ nonce: informatiqSP.nonce
+ },
+ success: function(response) {
+ if (response.success) {
+ var data = response.data;
+ var html = '';
+
+ if (data.products.length === 0) {
+ html = '| No in-stock products with SKU found. |
';
+ } else {
+ $.each(data.products, function(i, product) {
+ var localPrice = product.local_price ? data.currency + parseFloat(product.local_price).toFixed(2) : '-';
+ var googlePrice = product.google_price ? data.currency + parseFloat(product.google_price).toFixed(2) : '-';
+ var priceLabel = product.price_type === 'sale' ? ' (sale)' : ' (regular)';
+ var matchLabel = product.match_type ? product.match_type : '-';
+ var statusClass = product.found ? 'color: #00a32a;' : 'color: #d63638;';
+ var statusText = product.found ? 'Found' : 'Not Found';
+
+ if (product.found && product.google_offer) {
+ matchLabel += ' (' + product.google_offer + ')';
+ }
+
+ html += '';
+ html += '| ' + product.name + ' | ';
+ html += '' + product.sku + ' | ';
+ html += '' + localPrice + priceLabel + ' | ';
+ html += '' + googlePrice + ' | ';
+ html += '' + matchLabel + ' | ';
+ html += '' + statusText + ' | ';
+ html += '
';
+ });
+ }
+
+ $tbody.html(html);
+ $results.show();
+
+ // Show summary
+ var summary = 'Showing ' + data.products.length + ' WooCommerce products. ';
+ summary += data.google_count + ' products found in Google Merchant Center.';
+ $button.after('' + summary + '
');
+
+ } else {
+ alert('Error: ' + (response.data.message || 'Unknown error'));
+ }
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ alert('Error: ' + errorThrown);
+ },
+ complete: function() {
+ $button.prop('disabled', false);
+ $spinner.removeClass('is-active');
+ }
+ });
}
};