Changeset 3439817
- Timestamp:
- 01/14/2026 07:57:51 PM (3 months ago)
- Location:
- meliconnect/trunk
- Files:
-
- 15 edited
-
assets/css/plugin-pages.css (modified) (1 diff)
-
includes/Core/Assets/Js/meliconnect-setting.js (modified) (7 diffs)
-
includes/Core/CronManager.php (modified) (1 diff)
-
includes/Core/Helpers/Helper.php (modified) (3 diffs)
-
includes/Core/Models/ProcessItems.php (modified) (2 diffs)
-
includes/Core/Models/Template.php (modified) (1 diff)
-
includes/Modules/Importer/Assets/Js/meliconnect-importer.js (modified) (6 diffs)
-
includes/Modules/Importer/Controllers/ImportController.php (modified) (4 diffs)
-
includes/Modules/Importer/Models/UserListingToImport.php (modified) (3 diffs)
-
includes/Modules/Importer/Services/WooCommerceProductAdapter.php (modified) (1 diff)
-
includes/Modules/Importer/Services/WooCommerceProductCreationService.php (modified) (11 diffs)
-
includes/Modules/Importer/Views/importer.php (modified) (13 diffs)
-
meliconnect.php (modified) (2 diffs)
-
readme.txt (modified) (1 diff)
-
vendor/composer/installed.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
meliconnect/trunk/assets/css/plugin-pages.css
r3408382 r3439817 271 271 272 272 273 .meliconnect-select:not(.is-multiple):not(. is-loading)::after {273 .meliconnect-select:not(.is-multiple):not(.meliconnect-is-loading)::after { 274 274 border: none !important; 275 275 } -
meliconnect/trunk/includes/Core/Assets/Js/meliconnect-setting.js
r3367389 r3439817 158 158 processData: false, 159 159 beforeSend: function () { 160 $('#save-import-button').addClass(' is-loading');160 $('#save-import-button').addClass('meliconnect-is-loading'); 161 161 }, 162 162 success: function (response) { … … 164 164 }, 165 165 error: function (xhr, status, error) { 166 $('#save-import-button').removeClass(' is-loading');166 $('#save-import-button').removeClass('meliconnect-is-loading'); 167 167 console.log(xhr.responseText); 168 168 } … … 198 198 processData: false, 199 199 beforeSend: function () { 200 jQuery('#save-export-button').addClass(' is-loading');200 jQuery('#save-export-button').addClass('meliconnect-is-loading'); 201 201 }, 202 202 success: function (response) { … … 204 204 }, 205 205 error: function (xhr, status, error) { 206 jQuery('#save-export-button').removeClass(' is-loading');206 jQuery('#save-export-button').removeClass('meliconnect-is-loading'); 207 207 console.log(xhr.responseText); 208 208 } … … 269 269 processData: false, 270 270 beforeSend: function () { 271 $('#save-import-button').addClass(' is-loading');271 $('#save-import-button').addClass('meliconnect-is-loading'); 272 272 }, 273 273 success: function (response) { … … 329 329 processData: false, 330 330 beforeSend: function () { 331 $('#save-sync-button').addClass(' is-loading');331 $('#save-sync-button').addClass('meliconnect-is-loading'); 332 332 }, 333 333 success: function (response) { … … 335 335 }, 336 336 error: function (xhr, status, error) { 337 $('#save-sync-button').removeClass(' is-loading');337 $('#save-sync-button').removeClass('meliconnect-is-loading'); 338 338 console.log(xhr.responseText); 339 339 } -
meliconnect/trunk/includes/Core/CronManager.php
r3408382 r3439817 231 231 232 232 public function processUserCustomImport() { 233 global $wpdb; 234 $meli_listing_ids_arr = array(); 235 236 $lock = get_option( $this->custom_import_lock_option_name ); 237 238 if ( $lock ) { 239 Helper::logData( 'Custom import is in process. Aborting.', 'custom-import' ); 240 return; 241 } 242 243 // Update lock 244 update_option( $this->custom_import_lock_option_name, time() ); 245 246 try { 247 // 1- Get pending items from process items table 248 $items_to_process = $this->get_pending_items_to_process( 'custom-import' ); 249 250 if ( empty( $items_to_process ) ) { 251 return; 252 } 253 254 Helper::logData( 'Items to process: ' . count( $items_to_process ), 'custom-import' ); 255 256 // Create instances of the dependencies needed for ProductDataFacade 257 $wooCommerceAdapter = new WooCommerceProductAdapter(); 258 $productCreationService = new WooCommerceProductCreationService(); 259 $productDataFacade = new ProductDataFacade( $wooCommerceAdapter, $productCreationService ); 260 261 foreach ( $items_to_process as $item ) { 262 // Verificar si se ha solicitado la cancelación 263 $cancel_requested = get_option( 'meliconnect_import_cancel_requested' ); 264 265 Helper::logData( 'Cancel requested: ' . $cancel_requested, 'custom-import' ); 266 if ( $cancel_requested ) { 267 268 Helper::logData( 'Custom import canceled by user. Exiting process.', 'custom-import' ); 269 270 UserListingToImport::update_processing_listings( 'canceled' ); 271 272 throw new \Exception( 'Custom import canceled by user.' ); 273 } 274 275 Helper::logData( 'Processing listing id: ' . $item->meli_listing_id . ' - Status: ' . $item->process_status, 'custom-import' ); 276 277 try { 278 // Iniciar la transacción para el ítem actual 279 $wpdb->query( 'START TRANSACTION' ); 280 281 // 2- Format items data to send, Send data to API server and Get response and process response creating or updating items in WooCommerce 282 $productDataFacade->importAndCreateProduct( $item->meli_listing_id, $item->meli_user_id, $item->template_id, $item->woo_product_id ); 283 284 // 3- Update process and process items table 285 $process = ProcessItems::updateProcessedItemStatus( $item->id, 'processed', $item->process_id ); 286 287 Helper::logData( 'Process: ' . wp_json_encode( $process ), 'custom-import' ); 288 289 $meli_listing_ids_arr = array_merge( $meli_listing_ids_arr, array( $item->meli_listing_id ) ); 290 291 UserListingToImport::update_user_listing_item_import_status( array( $item->meli_listing_id ), 'finished' ); 292 293 // Commit the transaction if everything is successful for this item 294 $wpdb->query( 'COMMIT' ); 295 } catch ( \Exception $itemException ) { 296 // Log individual item error and rollback transaction 297 Helper::logData( 'Error processing listing id ' . $item->meli_listing_id . ': ' . $itemException->getMessage(), 'custom-import' ); 298 299 // Rollback the transaction for the current item 300 $wpdb->query( 'ROLLBACK' ); 301 } 302 } 303 } catch ( \Exception $e ) { 304 // Log the error message 305 Helper::logData( 'Error during custom import: ' . $e->getMessage(), 'custom-import' ); 306 } finally { 307 308 UserListingToImport::update_vinculated_product_ids( $meli_listing_ids_arr ); 309 // When cron finishes, remove lock 310 delete_option( $this->custom_import_lock_option_name ); 311 312 // Helper::logData('Custom import process finished. Deleting meliconnect_import_cancel_requested', 'custom-import'); 313 314 // Remove the cancel request flag 315 delete_option( 'meliconnect_import_cancel_requested' ); 316 } 317 } 233 global $wpdb; 234 235 $lock_name = $this->custom_import_lock_option_name; 236 $lock_ttl = 300; // 5 minutos 237 $batch_size = 20; 238 239 $processed_listing_ids = []; 240 $lock_acquired = false; 241 242 Helper::logData( 243 'CUSTOM IMPORT CRON START PID ' . getmypid(), 244 'custom-import' 245 ); 246 247 try { 248 249 /** 250 * LOCK CON TTL 251 */ 252 $existing_lock = get_option($lock_name); 253 if ( $existing_lock && ( time() - $existing_lock ) > $lock_ttl ) { 254 delete_option($lock_name); // lock vencido 255 } 256 257 $lock_acquired = add_option($lock_name, time(), '', 'no'); 258 if ( ! $lock_acquired ) { 259 Helper::logData('Custom import already running. Exit.', 'custom-import'); 260 return; 261 } 262 263 /** 264 * OBTENER BATCH 265 */ 266 $items = ProcessItems::getPendingBatch('custom-import', $batch_size); 267 268 if ( empty($items) ) { 269 Helper::logData('No pending items. Import finished.', 'custom-import'); 270 return; 271 } 272 273 /** 274 * MARCAR COMO PROCESSING 275 */ 276 $item_ids = wp_list_pluck($items, 'id'); 277 ProcessItems::markAsProcessing($item_ids); 278 279 $wooAdapter = new WooCommerceProductAdapter(); 280 $creator = new WooCommerceProductCreationService(); 281 $facade = new ProductDataFacade($wooAdapter, $creator); 282 283 /** 284 * PROCESAR BATCH 285 */ 286 foreach ( $items as $item ) { 287 288 if ( get_option('meliconnect_import_cancel_requested') ) { 289 Helper::logData('Custom import canceled by user.', 'custom-import'); 290 break; 291 } 292 293 Helper::logData( 294 'Processing listing ' . $item->meli_listing_id, 295 'custom-import' 296 ); 297 298 try { 299 $wpdb->query('START TRANSACTION'); 300 301 $facade->importAndCreateProduct( 302 $item->meli_listing_id, 303 $item->meli_user_id, 304 $item->template_id, 305 $item->woo_product_id 306 ); 307 308 ProcessItems::markAsProcessed($item->id, $item->process_id); 309 310 UserListingToImport::update_user_listing_item_import_status( 311 [$item->meli_listing_id], 312 'finished' 313 ); 314 315 $processed_listing_ids[] = $item->meli_listing_id; 316 317 $wpdb->query('COMMIT'); 318 319 } catch ( \Throwable $e ) { 320 321 $wpdb->query('ROLLBACK'); 322 323 ProcessItems::markAsFailed( 324 $item->id, 325 $item->process_id, 326 $e->getMessage() 327 ); 328 329 UserListingToImport::update_user_listing_item_import_status( 330 [$item->meli_listing_id], 331 'failed' 332 ); 333 334 Helper::logData( 335 'Error listing ' . $item->meli_listing_id . ': ' . $e->getMessage(), 336 'custom-import' 337 ); 338 } 339 } 340 341 } catch ( \Throwable $e ) { 342 343 344 Helper::logData( 345 'Fatal import error: ' . $e->getMessage(), 346 'custom-import' 347 ); 348 349 } finally { 350 351 if ( $lock_acquired ) { 352 delete_option($lock_name); 353 } 354 355 delete_option('meliconnect_import_cancel_requested'); 356 357 if ( ! empty($processed_listing_ids) ) { 358 UserListingToImport::update_vinculated_product_ids( 359 $processed_listing_ids 360 ); 361 } 362 363 Helper::logData( 364 'CUSTOM IMPORT CRON END', 365 'custom-import' 366 ); 367 } 368 } 318 369 319 370 public function processUserCustomExport() { -
meliconnect/trunk/includes/Core/Helpers/Helper.php
r3408382 r3439817 41 41 return $product_id ? (int) $product_id : null; 42 42 } 43 44 45 public static function canSetSku( $sku, $variation_id = null ) { 46 47 $sku = trim( (string) $sku ); 48 49 if ( $sku === '' ) { 50 return false; 51 } 52 53 $existing_id = wc_get_product_id_by_sku( $sku ); 54 55 if ( ! $existing_id ) { 56 return true; 57 } 58 59 // Permitir si es la misma variación (update) 60 if ( $variation_id && (int) $existing_id === (int) $variation_id ) { 61 return true; 62 } 63 64 return false; 65 } 66 43 67 44 68 … … 89 113 // Construir y devolver la URL base 90 114 return "$scheme://$host"; */ 115 116 if ( defined( 'WP_CLI' ) || php_sapi_name() === 'cli' ) { 117 $_SERVER['HTTPS'] = 'on'; 118 } 91 119 92 120 return get_site_url(); … … 500 528 501 529 public static function handleDismissNotifications() { 502 global $wpdb;530 global $wpdb; 503 531 504 532 if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'meliconnect_notifications_nonce' ) ) { -
meliconnect/trunk/includes/Core/Models/ProcessItems.php
r3367389 r3439817 16 16 } 17 17 18 public static function updateProcessedItemStatus( $item_process_id, $status, $process_id ) { 18 public static function getPendingBatch( string $type, int $limit ) { 19 global $wpdb; 20 21 $process = Process::getCurrentProcessData( $type, array( 'pending', 'processing' ) ); 22 23 if ( ! $process ) { 24 return array(); 25 } 26 27 return self::getProcessItems( 28 $process->process_id, 29 $limit, 30 'pending' 31 ); 32 } 33 34 public static function markAsProcessing( array $ids ) { 35 global $wpdb; 36 37 if ( empty( $ids ) ) { 38 return; 39 } 40 41 $placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) ); 42 43 $wpdb->query( 44 $wpdb->prepare( 45 "UPDATE {$wpdb->prefix}meliconnect_process_items 46 SET status = 'processing', updated_at = NOW() 47 WHERE id IN ($placeholders)", 48 $ids 49 ) 50 ); 51 } 52 53 public static function markAsProcessed( $item_id, $process_id ) { 54 return self::updateProcessedItemStatus( 55 $item_id, 56 'processed', 57 $process_id 58 ); 59 } 60 61 public static function markAsFailed( $item_id, $process_id, $error ) { 62 //Updates count of failed items in process table 63 self::updateProcessedItemStatus( 64 $item_id, 65 'failed', 66 $process_id 67 ); 68 69 global $wpdb; 70 71 $wpdb->update( 72 "{$wpdb->prefix}meliconnect_process_items", 73 array( 74 'process_status' => 'failed', 75 'process_error' => substr( $error, 0, 255 ), 76 'updated_at' => current_time( 'mysql' ), 77 ), 78 array( 79 'id' => $item_id, 80 'process_id' => $process_id, 81 ) 82 ); 83 } 84 85 public static function updateProcessedItemStatus( $item_process_id, $status, $process_id) { 19 86 global $wpdb; 20 87 … … 28 95 if ( $result_item !== false ) { 29 96 30 // update Process 31 $process = Process::updateProcessProgress( $process_id, true ); 97 if ( $status == 'failed' ) { 98 $process = Process::updateProcessProgress( $process_id, false ); 99 } else { 100 $process = Process::updateProcessProgress( $process_id, true ); 101 } 32 102 33 103 return $process; -
meliconnect/trunk/includes/Core/Models/Template.php
r3367389 r3439817 760 760 return false; 761 761 } 762 Helper::logData( 'variation attrs' );762 //Helper::logData( 'variation attrs' ); 763 763 foreach ( $meli_listing_data->variations as $variation ) { 764 764 $meli_variation_id = $variation->id; -
meliconnect/trunk/includes/Modules/Importer/Assets/Js/meliconnect-importer.js
r3367389 r3439817 2 2 3 3 $('#action-to-do').select2(); 4 5 $(document).on('click', '.meliconnect-remove-filter', function (e) { 6 e.preventDefault(); 7 8 const $tag = $(this).closest('.meliconnect-control'); 9 10 $tag.fadeOut(150, function () { 11 const filterKey = $tag.find('.meliconnect-remove-filter').data('filter'); 12 console.log(filterKey); 13 const url = new URL(window.location.href); 14 console.log(url); 15 16 url.searchParams.delete(filterKey); 17 url.searchParams.delete('paged'); 18 19 window.location.href = url.toString(); 20 }); 21 }); 4 22 5 23 $('.match-all-listings-with-products').on('click', function (e) { … … 40 58 }, 41 59 complete: function () { 42 // Remover las clases 'disabled' e ' is-loading' cuando la solicitud AJAX termine60 // Remover las clases 'disabled' e 'meliconnect-is-loading' cuando la solicitud AJAX termine 43 61 $button.removeClass('disabled meliconnect-is-loading'); 44 62 } … … 140 158 processData: false, 141 159 beforeSend: function () { 142 $('#meliconnect-get-meli-user-listings-button').addClass(' is-loading');160 $('#meliconnect-get-meli-user-listings-button').addClass('meliconnect-is-loading'); 143 161 }, 144 162 success: function (response) { … … 154 172 }); 155 173 156 $('#meliconnect-get-meli-user-listings-button').removeClass(' is-loading');174 $('#meliconnect-get-meli-user-listings-button').removeClass('meliconnect-is-loading'); 157 175 }, 158 176 error: function (xhr, status, error) { … … 164 182 }); 165 183 166 $('#meliconnect-get-meli-user-listings-button').removeClass(' is-loading');184 $('#meliconnect-get-meli-user-listings-button').removeClass('meliconnect-is-loading'); 167 185 } 168 186 }); … … 315 333 data: { 316 334 action: 'meliconnect_init_import_process', 317 nonce: meliconnect_translations.init_import_process_nonce 335 nonce: meliconnect_translations.init_import_process_nonce, 336 filters: window.location.search 318 337 }, 319 338 success: function (response) { -
meliconnect/trunk/includes/Modules/Importer/Controllers/ImportController.php
r3372090 r3439817 274 274 } 275 275 276 self::initImportProcess(); 276 $filters = []; 277 278 if ( ! empty( $_POST['filters'] ) ) { 279 parse_str( ltrim( $_POST['filters'], '?' ), $filters ); 280 } 281 282 283 284 self::initImportProcessFiltered($filters); 277 285 278 286 wp_send_json_success(); … … 315 323 } 316 324 317 // UserListingToImport::cancel_import_process();325 UserListingToImport::update_processing_listings('pending'); 318 326 319 327 update_option( 'meliconnect_import_cancel_requested', true ); … … 592 600 } 593 601 602 public static function initImportProcessFiltered( array $filters ) { 603 604 $items = UserListingToImport::get_user_listings_to_import_filtered( $filters ); 605 606 if ( empty( $items ) ) { 607 Helper::logData( 'No items found to import', 'initImportProcessFiltered' ); 608 return false; 609 } 610 611 /* global $wpdb; 612 echo PHP_EOL . '-------------------- last query --------------------' . PHP_EOL; 613 echo '<pre>' . var_export( $wpdb->last_query, true) . '</pre>'; 614 echo PHP_EOL . '------------------- FINISHED ---------------------' . PHP_EOL; 615 echo PHP_EOL . '-------------------- items --------------------' . PHP_EOL; 616 echo '<pre>' . var_export( count( $items ), true) . '</pre>'; 617 echo PHP_EOL . '------------------- FINISHED ---------------------' . PHP_EOL; */ 618 619 $formatedItems = []; 620 621 foreach ( $items as $item ) { 622 $formatedItems[] = [ 623 'meli_user_id' => $item->meli_user_id, 624 'meli_listing_id' => $item->meli_listing_id, 625 'woo_product_id' => $item->vinculated_product_id, 626 'template_id' => $item->vinculated_template_id, 627 'process_status' => 'processing', 628 ]; 629 } 630 631 $process_id = Process::createProcess( 'custom-import', $formatedItems ); 632 633 if ( ! $process_id ) { 634 return false; 635 } 636 637 $meli_listing_ids = array_column( $items, 'meli_listing_id' ); 638 639 640 641 UserListingToImport::update_user_listing_item_import_status( 642 $meli_listing_ids, 643 'processing' 644 ); 645 646 return true; 647 } 648 594 649 public static function multiGetListingsData( $seller_data, $meli_user_listings_ids ) { 595 650 $meli_user_listings_ids_chunk = array_chunk( $meli_user_listings_ids, 20 ); … … 645 700 $base_url = 'users/' . $seller_data->user_id . '/items/search?search_type=scan'; 646 701 $items = MeliconMeli::getWithHeader( $base_url, $seller_data->access_token ); 647 echo PHP_EOL . '-------------------- $items --------------------' . PHP_EOL; 648 echo '<pre>' . var_export( $items, true) . '</pre>'; 649 echo PHP_EOL . '------------------- FINISHED ---------------------' . PHP_EOL; 702 650 703 if ( ! isset( $items['body']->results ) || ! is_iterable( $items['body']->results ) ) { 651 704 Helper::logData( 'Error getting products from seller: ' . $seller_data->user_id, 'importer' ); -
meliconnect/trunk/includes/Modules/Importer/Models/UserListingToImport.php
r3367389 r3439817 59 59 public static function apply_item_manual_match( $meli_item_id, $woo_product_id ) {} 60 60 61 62 61 63 public static function update_meli_user_listings_extra_data_to_import( $meli_user_listings_data ) { 62 64 global $wpdb; … … 97 99 'vinculated_product_id' => $listing_data['vinculated_product_id'], 98 100 'vinculated_template_id' => $listing_data['vinculated_template_id'], 101 'import_status' => 'pending', 99 102 ), 100 103 array( … … 161 164 // phpcs:enable 162 165 } 166 167 public static function get_user_listings_to_import_filtered( array $filters ) { 168 global $wpdb; 169 self::init(); 170 171 $table_name = self::$table_name; 172 $where = []; 173 $params = []; 174 175 // Solo pendientes 176 $where[] = "(import_status = 'pending' )"; 177 178 // Search 179 if ( ! empty( $filters['search'] ) ) { 180 $where[] = "(meli_listing_title LIKE %s OR meli_listing_id LIKE %s OR meli_sku LIKE %s)"; 181 $search = '%' . $wpdb->esc_like( $filters['search'] ) . '%'; 182 183 $params[] = $search; 184 $params[] = $search; 185 $params[] = $search; 186 } 187 188 // Seller 189 if ( ! empty( $filters['seller'] ) ) { 190 $where[] = "meli_user_id = %d"; 191 $params[] = (int) $filters['seller']; 192 } 193 194 // Vinculation 195 if ( ! empty( $filters['vinculation_filter'] ) ) { 196 197 if ( $filters['vinculation_filter'] === 'no_product' ) { 198 $where[] = "(vinculated_product_id IS NULL OR vinculated_product_id = 0)"; 199 } 200 201 if ( $filters['vinculation_filter'] === 'yes_product' ) { 202 $where[] = "(vinculated_product_id IS NOT NULL AND vinculated_product_id > 0)"; 203 } 204 } 205 206 // Status 207 if ( ! empty( $filters['listing_status_filter'] ) ) { 208 $where[] = "meli_status = %s"; 209 $params[] = $filters['listing_status_filter']; 210 } 211 212 // Listing type 213 if ( ! empty( $filters['listing_type_filter'] ) ) { 214 $where[] = "meli_product_type = %s"; 215 $params[] = $filters['listing_type_filter']; 216 } 217 218 $sql = "SELECT * FROM {$table_name}"; 219 220 if ( $where ) { 221 $sql .= ' WHERE ' . implode( ' AND ', $where ); 222 } 223 224 225 226 // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared 227 return $params 228 ? $wpdb->get_results( $wpdb->prepare( $sql, ...$params ) ) 229 : $wpdb->get_results( $sql ); 230 // phpcs:enable 231 } 163 232 164 233 -
meliconnect/trunk/includes/Modules/Importer/Services/WooCommerceProductAdapter.php
r3367389 r3439817 49 49 $server_response = $this->sendDataToServer( $rawData ); 50 50 51 Helper::logData('Server response:' . $server_response, 'custom-import');51 //Helper::logData('Server response:' . $server_response, 'custom-import'); 52 52 53 53 return json_decode( $server_response, true ); -
meliconnect/trunk/includes/Modules/Importer/Services/WooCommerceProductCreationService.php
r3372090 r3439817 58 58 } 59 59 60 Helper::logData( 'Product type: ' . $product_data['type'], 'custom-import' ); 61 60 62 // Create a product with basic data and saves it 61 63 $woo_product = $this->createBaseProduct( $woo_product, $product_data ); … … 115 117 Helper::logData( 'Woo Product id: ' . $woo_product->get_id(), 'custom-import' ); 116 118 117 Helper::logData( 'Product data: ' . wp_json_encode( $product_data ), 'custom-import' ); 119 //Helper::logData( 'Product data: ' . wp_json_encode( $product_data ), 'custom-import' ); 120 121 $meli_seller_id = $product_data['extra_data']['postmetas']['meliconnect_meli_seller_id'] ?? null; 118 122 119 123 // Asignar el título del producto … … 127 131 // Verificar si el SKU ya existe 128 132 $existing_product_id = Helper::get_active_product_id_by_sku( $product_data['sku'] ); 133 if ( $sku ) { 134 update_post_meta( 135 $woo_product->get_id(), 136 '_meliconnect_sku', 137 $product_data['sku'] 138 ); 139 } 129 140 130 141 if ( $existing_product_id ) { … … 141 152 142 153 if ( isset( $product_data['gtin'] ) && $product_data['gtin'] !== false ) { 143 $woo_product->set_global_unique_id( $product_data['gtin'] ); 144 Helper::logData( 'GTIN: ' . $product_data['gtin'], 'custom-import' ); 154 155 Helper::logData( 'GTIN: ' . $product_data['gtin'], 'custom-import' ); 156 157 158 //Because GTIN is validated by woocommerce, we need to save it as a postmeta 159 //$woo_product->set_global_unique_id( $product_data['gtin'] ); 160 161 update_post_meta( 162 $woo_product->get_id(), 163 '_meliconnect_gtin', 164 $product_data['gtin'] 165 ); 166 145 167 } else { 146 168 Helper::logData( 'GTIN ignored by settings', 'custom-import' ); 147 169 } 170 148 171 149 172 // Descripciones … … 197 220 // Imágenes 198 221 if ( isset( $product_data['pictures']['main_image'] ) && $product_data['pictures']['main_image'] !== false ) { 199 $this->create_or_update_main_image( $woo_product->get_id(), $product_data['pictures']['main_image'] );222 $this->create_or_update_main_image( $woo_product->get_id(), $product_data['pictures']['main_image'], $meli_seller_id ); 200 223 } else { 201 224 Helper::logData( 'Main image ignored by settings', 'custom-import' ); … … 203 226 204 227 if ( isset( $product_data['pictures']['gallery_images'] ) && $product_data['pictures']['gallery_images'] !== false ) { 205 $this->create_or_update_gallery_images( $woo_product->get_id(), $product_data['pictures']['gallery_images'] );228 $this->create_or_update_gallery_images( $woo_product->get_id(), $product_data['pictures']['gallery_images'], $meli_seller_id ); 206 229 } else { 207 230 Helper::logData( 'Gallery images ignored by settings', 'custom-import' ); … … 305 328 306 329 $variation->set_regular_price( $variation_data['price'] ); 307 $variation->set_sku( $variation_data['sku'] ); 330 331 $sku = trim( $variation_data['sku'] ) ?? ''; 332 333 if ( $sku ) { 334 update_post_meta( 335 $existing_variation_id , 336 '_meliconnect_sku', 337 $sku 338 ); 339 } 340 341 if ( Helper::canSetSku( $sku, $existing_variation_id ) ) { 342 343 $variation->set_sku( $sku ); 344 345 } else { 346 Helper::logData( 347 'Variation SKU skipped because it already exists. SKU="' . $sku . '" Product=' . $product_id, 348 'custom-import' 349 ); 350 } 351 308 352 $variation->set_stock_quantity( $variation_data['available_quantity'] ); 309 353 $variation->set_manage_stock( $variation_data['manage_stock'] ); … … 358 402 } 359 403 } 360 361 // Asignar SKU y registrar 362 if ( $sku ) { 363 $variation->set_sku( $sku ); 364 // Helper::logData('Assigned SKU: ' . $sku, 'custom-import'); 365 } 404 405 if ( $sku ) { 406 update_post_meta( 407 $variation->get_id() , 408 '_meliconnect_sku', 409 $sku 410 ); 411 } 412 413 if ( Helper::canSetSku( $sku, $variation->get_id() ) ) { 414 415 $variation->set_sku( $sku ); 416 417 Helper::logData('Assigned SKU from Meli attribute: ' . $sku, 'custom-import'); 418 419 } else { 420 Helper::logData( 421 'Variation Attr SKU skipped because it already exists. SKU="' . $sku . '" Variation ID =' . $variation->get_id() , 422 'custom-import' 423 ); 424 } 366 425 367 426 // Guardar GTIN como postmeta y registrar resultado … … 369 428 $result = update_post_meta( $variation->get_id(), '_global_unique_id', $gtin ); 370 429 if ( $result === false ) { 371 //Helper::logData('Failed to update GTIN for variation ID ' . $variation->get_id(), 'custom-import');372 } else { 373 //Helper::logData('Successfully updated GTIN for variation ID ' . $variation->get_id(), 'custom-import');430 Helper::logData('Failed to update GTIN for variation ID ' . $variation->get_id(), 'custom-import'); 431 } else { 432 Helper::logData('Successfully updated GTIN for variation ID ' . $variation->get_id(), 'custom-import'); 374 433 } 375 434 } … … 581 640 582 641 583 private function create_or_update_main_image( $post_id, $main_image_data ) {642 private function create_or_update_main_image( $post_id, $main_image_data, $seller_id = null ) { 584 643 // Extraer el ID de la imagen 585 644 $image_id = $main_image_data['id']; 586 645 587 $seller_id = get_post_meta( $post_id, 'meliconnect_meli_seller_id', true ); 646 if(empty($seller_id)){ 647 $seller_id = get_post_meta( $post_id, 'meliconnect_meli_seller_id', true ); 648 } 649 588 650 $access_token = UserConnection::get_meli_access_token_by_seller( $seller_id ); 589 651 … … 745 807 746 808 747 private function create_or_update_gallery_images( $post_id, $gallery_images_data ) {809 private function create_or_update_gallery_images( $post_id, $gallery_images_data , $meli_seller_id =null ) { 748 810 $gallery_ids = array(); 749 $meli_seller_id = get_post_meta( $post_id, 'meliconnect_meli_seller_id', true ); 811 812 if(empty($meli_seller_id)){ 813 $meli_seller_id = get_post_meta( $post_id, 'meliconnect_meli_seller_id', true ); 814 } 815 750 816 751 817 foreach ( $gallery_images_data as $image_data ) { -
meliconnect/trunk/includes/Modules/Importer/Views/importer.php
r3372090 r3439817 4 4 exit; // Exit if accessed directly 5 5 } 6 7 use Meliconnect\Meliconnect\Core\Helpers\Helper; 6 8 use Meliconnect\Meliconnect\Modules\Importer\Controllers\ImportController; 7 9 … … 14 16 require MELICONNECT_PLUGIN_ROOT . 'includes/Core/Views/Partials/header.php'; 15 17 18 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Solo lectura de parámetros de URL. 19 $search_value = isset( $_GET['search'] ) ? sanitize_text_field( wp_unslash( $_GET['search'] ) ) : ''; 20 $selected_vinculation = isset( $_GET['vinculation_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['vinculation_filter'] ) ) : ''; 21 $selected_listing_status = isset( $_GET['listing_status_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['listing_status_filter'] ) ) : ''; 22 $selected_template = isset( $_GET['template_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['template_filter'] ) ) : ''; 23 $selected_listing_type = isset( $_GET['listing_type_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['listing_type_filter'] ) ) : ''; 24 $selected_seller = isset( $_GET['seller_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['seller_filter'] ) ) : ''; 25 26 $total_filtered_items = Meliconnect\Meliconnect\Modules\Importer\UserListingsTable::record_count(); 27 28 29 // phpcs:enable WordPress.Security.NonceVerification.Recommended 16 30 ?> 31 32 17 33 <!-- START MCSYNCAPP --> 18 34 <div id="meliconnect-page-importer-main" class="meliconnect-app"> … … 21 37 <?php if ( ! empty( $data['sellers_exceeding_limit'] ) ) : ?> 22 38 <div class="meliconnect-notification meliconnect-is-warning meliconnect-is-light"> 23 <button class="meliconnect-delete"></button>24 <p>25 <i class="fas fa-exclamation-triangle"></i>39 <button class="meliconnect-delete"></button> 40 <p> 41 <i class="fas fa-exclamation-triangle"></i> 26 42 <?php 27 43 printf( … … 110 126 </div> 111 127 112 <div style="display: flex;" >128 <div style="display: flex;" class="meliconnect-is-hidden-touch"> 113 129 <div style="flex: 1;height: 100px; background-color: #f4f5f8"></div> 114 130 <div class="divider meliconnect-is-vertical"> >> </div> … … 164 180 </div> 165 181 166 <div style="display: flex;" >182 <div style="display: flex;" class="meliconnect-is-hidden-touch"> 167 183 <div style="flex: 1;height: 100px; background-color: #f4f5f8"></div> 168 <div class="divider meliconnect-is-vertical "> >> </div>184 <div class="divider meliconnect-is-vertical is-hidden-touch"> >> </div> 169 185 <div style="flex: 1;height: 100px; background-color: #f4f5f8"></div> 170 186 </div> … … 189 205 <form class="is-flex meliconnect-is-flex-direction-column" id="meliconnect-get-meli-user-listings" method="POST"> 190 206 <div class="meliconnect-field mb-3"> 191 <label class="meliconnect-label"><?php esc_html_e( 'Sel ect seller', 'meliconnect' ); ?></label>207 <label class="meliconnect-label"><?php esc_html_e( 'Seller', 'meliconnect' ); ?></label> 192 208 193 209 <?php … … 214 230 if ( $data['meli_user_listings_to_import_count'] > 0 ) { 215 231 ?> 216 <div style="display: flex;" >232 <div style="display: flex;" class="meliconnect-is-hidden-touch"> 217 233 <div style="flex: 1;height: 100px; background-color: #f4f5f8"></div> 218 234 <div class="divider meliconnect-is-vertical"> > </div> … … 237 253 </div> 238 254 239 <div style="display: flex;" >255 <div style="display: flex;" class="meliconnect-is-hidden-touch"> 240 256 <div style="flex: 1;height: 100px; background-color: #f4f5f8"></div> 241 257 <div class="divider meliconnect-is-vertical"> >> </div> … … 245 261 <!-- Buttons Column --> 246 262 <div class="meliconnect-column meliconnect-is-3"> 247 <p><strong><?php esc_html_e( 'Mercadolibre', 'meliconnect' ); ?></strong> </p> 248 <p><?php esc_html_e( 'Total active items', 'meliconnect' ); ?> : 249 <span id="meliconnect-import-seller-total-items-active"> 250 <?php echo esc_html( $data['meli_user_listings_active_to_import_count'] ); ?> 263 <p><strong><?php esc_html_e( 'Active filters', 'meliconnect' ); ?></strong></p> 264 265 <?php 266 $active_filters = array(); 267 268 // Search 269 if ( $search_value ) { 270 $active_filters['s'] = array( 271 'name' => 'search', 272 'label' => __( 'Search', 'meliconnect' ), 273 'value' => $search_value, 274 ); 275 } 276 277 // Vinculation 278 if ( $selected_vinculation ) { 279 280 if ( $selected_vinculation == 'yes_product' ) { 281 $selected_vinculation_text = 'To update'; 282 } elseif ( $selected_vinculation == 'no_product' ) { 283 $selected_vinculation_text = 'To create'; 284 } 285 286 $active_filters['vinculation'] = array( 287 'name' => 'vinculation_filter', 288 'label' => __( 'Action', 'meliconnect' ), 289 'value' => ucfirst( str_replace( '_', ' ', $selected_vinculation_text ) ), 290 ); 291 } 292 293 // Status 294 if ( $selected_listing_status ) { 295 $active_filters['status'] = array( 296 'name' => 'listing_status_filter', 297 'label' => __( 'Status', 'meliconnect' ), 298 'value' => ucfirst( str_replace( '_', ' ', $selected_listing_status ) ), 299 ); 300 } 301 302 // Type 303 if ( $selected_listing_type ) { 304 $active_filters['type'] = array( 305 'name' => 'listing_type_filter', 306 'label' => __( 'Type', 'meliconnect' ), 307 'value' => ucfirst( $selected_listing_type ), 308 ); 309 } 310 311 // Seller 312 if ( $selected_seller ) { 313 $active_filters['seller'] = array( 314 'name' => 'seller_filter', 315 'label' => __( 'Seller', 'meliconnect' ), 316 'value' => $selected_seller, 317 ); 318 } 319 ?> 320 321 <?php if ( empty( $active_filters ) ) : ?> 322 323 <p class="has-text-grey"> 324 <?php esc_html_e( 'No filters applied', 'meliconnect' ); ?> 325 </p> 326 327 <?php else : ?> 328 329 <div class="meliconnect-field meliconnect-is-grouped meliconnect-is-grouped-multiline meliconnect-active-filters"> 330 331 <?php foreach ( $active_filters as $key => $filter ) : ?> 332 <div class="meliconnect-control"> 333 <div class="meliconnect-tags meliconnect-has-addons"> 334 <span class="meliconnect-tag meliconnect-is-link"> 335 <?php echo esc_html( $filter['value'] ); ?> 336 </span> 337 <a 338 href="#" 339 class="meliconnect-tag meliconnect-is-delete meliconnect-remove-filter" 340 data-filter="<?php echo esc_attr( $filter['name'] ); ?>"> 341 </a> 342 </div> 343 </div> 344 <?php endforeach; ?> 345 346 </div> 347 348 <?php endif; ?> 349 350 <div> 351 <strong class="meliconnect-is-size-5"><?php esc_html_e( 'Total to import', 'meliconnect' ); ?> </strong> : 352 <span id="meliconnect-products-to-process-total"> 353 <?php echo esc_html( $total_filtered_items ); ?> 251 354 </span> 252 </p> 253 <p><?php esc_html_e( 'Not active items', 'meliconnect' ); ?> : 254 <span id="meliconnect-import-seller-total-items-not-actived"> 255 <?php echo esc_html( ( $data['meli_user_listings_to_import_count'] - $data['meli_user_listings_active_to_import_count'] ) ); ?> 256 </span> 257 </p> 258 259 <p><strong><?php esc_html_e( 'Woocommerce', 'meliconnect' ); ?></strong> </p> 260 <p> 261 <?php esc_html_e( 'Vinculated Products', 'meliconnect' ); ?> : 262 <span id="meliconnect-import-seller-total-products-vinculated"> 263 <?php echo esc_html( $data['woo_total_vinculated_products'] ); ?> 264 </span> 265 </p> 266 <p> 267 <?php esc_html_e( 'Not Vinculated Products', 'meliconnect' ); ?> : 268 <span id="meliconnect-import-seller-total-products-desvinculated"> 269 <?php echo esc_html( ( $data['woo_total_active_products'] - $data['woo_total_vinculated_products'] ) ); ?> 270 </span> 271 </p> 355 </div> 272 356 <div class="meliconnect-control meliconnect-mt-4"> 273 357 <button id="meliconnect-process-import-button" class="meliconnect-button meliconnect-is-success meliconnect-is-fullwidth"> … … 300 384 <div class="meliconnect-columns "> 301 385 <div class="meliconnect-column"> 302 <?php 303 // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Solo lectura de parámetros de URL. 304 $search_value = isset( $_GET['search'] ) ? sanitize_text_field( wp_unslash( $_GET['search'] ) ) : ''; 305 $selected_vinculation = isset( $_GET['vinculation_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['vinculation_filter'] ) ) : ''; 306 $selected_listing_status = isset( $_GET['listing_status_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['listing_status_filter'] ) ) : ''; 307 $selected_template = isset( $_GET['template_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['template_filter'] ) ) : ''; 308 $selected_listing_type = isset( $_GET['listing_type_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['listing_type_filter'] ) ) : ''; 309 $selected_seller = isset( $_GET['seller_filter'] ) ? sanitize_text_field( wp_unslash( $_GET['seller_filter'] ) ) : ''; 310 // phpcs:enable WordPress.Security.NonceVerification.Recommended 311 ?> 386 312 387 <div class="meliconnect-field meliconnect-has-addons"> 313 388 <div class="meliconnect-control"> … … 318 393 <div class="meliconnect-select meliconnect-is-fullwidth"> 319 394 <select class="meliconnect-select" name="vinculation_filter"> 320 <option value=""><?php esc_html_e( ' All Vinculations', 'meliconnect' ); ?></option>321 <option value="yes_product" <?php selected( $selected_vinculation, 'yes_product' ); ?>><?php esc_html_e( ' With Vinculated Product', 'meliconnect' ); ?></option>322 <option value="no_product" <?php selected( $selected_vinculation, 'no_product' ); ?>><?php esc_html_e( ' Without Vinculated Product', 'meliconnect' ); ?></option>395 <option value=""><?php esc_html_e( 'To update or create', 'meliconnect' ); ?></option> 396 <option value="yes_product" <?php selected( $selected_vinculation, 'yes_product' ); ?>><?php esc_html_e( 'Only to update', 'meliconnect' ); ?></option> 397 <option value="no_product" <?php selected( $selected_vinculation, 'no_product' ); ?>><?php esc_html_e( 'Only to create', 'meliconnect' ); ?></option> 323 398 <!-- <option value="yes_template" <?php selected( $selected_template, 'yes_template' ); ?>><?php esc_html_e( 'With Vinculated Template', 'meliconnect' ); ?></option> 324 399 <option value="no_template" <?php selected( $selected_template, 'no_template' ); ?>><?php esc_html_e( 'Without Vinculated Template', 'meliconnect' ); ?></option> --> … … 347 422 </div> 348 423 424 <?php 425 426 $sellers = Helper::getSellersIdsAndNames(); 427 428 if ( empty( $sellers ) && is_iterable( $sellers ) && count( $sellers ) > 1 ) { 429 430 ?> 431 349 432 <div class="meliconnect-control meliconnect-is-expanded"> 350 433 <div class="meliconnect-select meliconnect-is-fullwidth"> … … 357 440 </div> 358 441 </div> 442 443 <?php } ?> 359 444 360 445 <div class="meliconnect-control"> -
meliconnect/trunk/meliconnect.php
r3408382 r3439817 4 4 Plugin URI: https://mercadolibre.meliconnect.com/ 5 5 Description: WooCommerce & Mercado Libre integration to import, export, and synchronize products between your WooCommerce store and Mercado Libre accounts. 6 Version: 1. 3.26 Version: 1.4.0 7 7 Author: meliconnect 8 8 Text Domain: meliconnect … … 26 26 * Define constantes del plugin 27 27 */ 28 define( 'MELICONNECT_VERSION', '1. 3.2' );28 define( 'MELICONNECT_VERSION', '1.4.0' ); 29 29 define( 'MELICONNECT_DATABASE_VERSION', '1.1.1' ); 30 30 define( 'MELICONNECT_TEXTDOMAIN', 'meliconnect' ); -
meliconnect/trunk/readme.txt
r3408382 r3439817 5 5 Requires at least: 5.8 6 6 Requires PHP: 8.0 7 Tested up to: 6. 88 Stable tag: 1. 3.27 Tested up to: 6.9 8 Stable tag: 1.4.0 9 9 License: GPLv3 10 10 License URI: https://www.gnu.org/licenses/gpl-3.0.html -
meliconnect/trunk/vendor/composer/installed.php
r3408382 r3439817 4 4 'pretty_version' => 'dev-main', 5 5 'version' => 'dev-main', 6 'reference' => ' 79df82fcd1a40f7146c829825bb50a99eb01d76f',6 'reference' => 'e8b468faf960e6fd332bd847ae2f031be364d0b4', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../', … … 14 14 'pretty_version' => 'dev-main', 15 15 'version' => 'dev-main', 16 'reference' => ' 79df82fcd1a40f7146c829825bb50a99eb01d76f',16 'reference' => 'e8b468faf960e6fd332bd847ae2f031be364d0b4', 17 17 'type' => 'wordpress-plugin', 18 18 'install_path' => __DIR__ . '/../../',
Note: See TracChangeset
for help on using the changeset viewer.