Changeset 3493482
- Timestamp:
- 03/28/2026 05:19:26 PM (5 days ago)
- Location:
- api-isarud
- Files:
-
- 10 deleted
- 4 edited
- 7 copied
-
tags/6.2.0 (copied) (copied from api-isarud/trunk)
-
tags/6.2.0/api-isarud-tr_TR.mo (copied) (copied from api-isarud/trunk/api-isarud-tr_TR.mo)
-
tags/6.2.0/api-isarud-tr_TR.po (copied) (copied from api-isarud/trunk/api-isarud-tr_TR.po)
-
tags/6.2.0/api-isarud.php (copied) (copied from api-isarud/trunk/api-isarud.php) (1 diff)
-
tags/6.2.0/assets/banner-772x250.png (deleted)
-
tags/6.2.0/assets/icon-128x128.png (deleted)
-
tags/6.2.0/assets/icon-256x256.png (deleted)
-
tags/6.2.0/assets/logo-gif.gif (deleted)
-
tags/6.2.0/assets/screenshot-1.png (deleted)
-
tags/6.2.0/assets/screenshot-2.png (deleted)
-
tags/6.2.0/assets/screenshot-3.png (deleted)
-
tags/6.2.0/assets/screenshot-4.png (deleted)
-
tags/6.2.0/assets/screenshot-5.png (deleted)
-
tags/6.2.0/assets/screenshot-6.png (deleted)
-
tags/6.2.0/isarud-cloud-sync.php (copied) (copied from api-isarud/trunk/isarud-cloud-sync.php) (4 diffs)
-
tags/6.2.0/readme-tr_TR.txt (copied) (copied from api-isarud/trunk/readme-tr_TR.txt) (1 diff)
-
tags/6.2.0/readme.txt (copied) (copied from api-isarud/trunk/readme.txt) (1 diff)
-
trunk/api-isarud.php (modified) (1 diff)
-
trunk/isarud-cloud-sync.php (modified) (4 diffs)
-
trunk/readme-tr_TR.txt (modified) (1 diff)
-
trunk/readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
api-isarud/tags/6.2.0/api-isarud.php
r3493435 r3493482 17 17 if (!defined('ABSPATH')) exit; 18 18 19 define('ISARUD_VERSION', '6. 1.0');19 define('ISARUD_VERSION', '6.2.0'); 20 20 define('ISARUD_DIR', plugin_dir_path(__FILE__)); 21 21 define('ISARUD_URL', plugin_dir_url(__FILE__)); -
api-isarud/tags/6.2.0/isarud-cloud-sync.php
r3493435 r3493482 2 2 /** 3 3 * Isarud Cloud Sync — isarud.com API v2 entegrasyonu 4 * WP Plugin v6. 1.04 * WP Plugin v6.2.0 5 5 */ 6 6 if (!defined('ABSPATH')) exit; … … 19 19 add_action('isarud_cloud_sync_hook', [$this, 'run_cloud_sync']); 20 20 add_action('woocommerce_new_order', [$this, 'sync_order_to_cloud'], 40, 1); 21 22 21 if (get_option('isarud_cloud_enabled') === 'yes') { 23 22 if (!wp_next_scheduled('isarud_cloud_sync_hook')) { … … 27 26 } 28 27 29 private function get_cloud_key(): string { 30 return get_option('isarud_cloud_api_key', ''); 31 } 32 33 public function is_enabled(): bool { 34 return get_option('isarud_cloud_enabled') === 'yes' && !empty($this->get_cloud_key()); 35 } 28 private function get_cloud_key(): string { return get_option('isarud_cloud_api_key', ''); } 29 public function is_enabled(): bool { return get_option('isarud_cloud_enabled') === 'yes' && !empty($this->get_cloud_key()); } 36 30 37 31 private function api_request(string $endpoint, array $data = [], string $method = 'POST'): array { 38 32 $key = $this->get_cloud_key(); 39 33 if (empty($key)) return ['error' => 'Cloud API key not configured']; 40 41 $args = [ 42 'method' => $method, 43 'timeout' => 30, 44 'headers' => [ 45 'Content-Type' => 'application/json', 46 'X-Marketplace-Key' => $key, 47 'User-Agent' => 'IsarudWP/' . ISARUD_VERSION, 48 ], 49 ]; 50 51 if (!empty($data) && in_array($method, ['POST', 'PUT'])) { 52 $args['body'] = wp_json_encode($data); 53 } 54 34 $args = ['method' => $method, 'timeout' => 30, 'headers' => ['Content-Type' => 'application/json', 'X-Marketplace-Key' => $key, 'User-Agent' => 'IsarudWP/' . ISARUD_VERSION]]; 35 if (!empty($data) && in_array($method, ['POST', 'PUT'])) $args['body'] = wp_json_encode($data); 55 36 $response = wp_remote_request($this->api_base . $endpoint, $args); 56 57 if (is_wp_error($response)) { 58 return ['error' => $response->get_error_message()]; 59 } 60 37 if (is_wp_error($response)) return ['error' => $response->get_error_message()]; 61 38 $code = wp_remote_retrieve_response_code($response); 62 39 $body = json_decode(wp_remote_retrieve_body($response), true) ?: []; 63 64 if ($code >= 400) { 65 return ['error' => $body['error'] ?? "HTTP {$code}"]; 66 } 67 40 if ($code >= 400) return ['error' => $body['error'] ?? "HTTP {$code}"]; 68 41 return $body; 69 42 } 70 43 71 44 public function connect_site(string $bearer_token): array { 72 $response = wp_remote_post('https://isarud.com/api/v2/marketplace/connect', [ 73 'timeout' => 30, 74 'headers' => [ 75 'Content-Type' => 'application/json', 76 'Authorization' => 'Bearer ' . $bearer_token, 77 ], 78 'body' => wp_json_encode([ 79 'platform' => 'wordpress', 80 'site_url' => home_url(), 81 'site_name' => get_bloginfo('name'), 82 ]), 83 ]); 84 85 if (is_wp_error($response)) { 86 return ['error' => $response->get_error_message()]; 87 } 88 45 $response = wp_remote_post('https://isarud.com/api/v2/marketplace/connect', ['timeout' => 30, 'headers' => ['Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $bearer_token], 'body' => wp_json_encode(['platform' => 'wordpress', 'site_url' => home_url(), 'site_name' => get_bloginfo('name')])]); 46 if (is_wp_error($response)) return ['error' => $response->get_error_message()]; 89 47 $body = json_decode(wp_remote_retrieve_body($response), true) ?: []; 90 91 48 if (!empty($body['success']) && !empty($body['platform']['api_key'])) { 92 49 update_option('isarud_cloud_api_key', $body['platform']['api_key']); … … 96 53 return ['success' => true, 'message' => 'Connected to isarud.com']; 97 54 } 98 99 if (isset($body['error']) && strpos($body['error'], 'already connected') !== false) { 100 return ['success' => true, 'message' => 'Already connected']; 101 } 102 55 if (isset($body['error']) && strpos($body['error'], 'already connected') !== false) return ['success' => true, 'message' => 'Already connected']; 103 56 return ['error' => $body['error'] ?? 'Connection failed']; 104 57 } 105 58 106 59 public function sync_products(): array { 107 if (!$this->is_enabled() || !class_exists('WooCommerce')) { 108 return ['error' => 'Cloud sync not enabled or WooCommerce not active']; 109 } 110 60 if (!$this->is_enabled() || !class_exists('WooCommerce')) return ['error' => 'Cloud sync not enabled or WooCommerce not active']; 111 61 global $wpdb; 112 $marketplaces = $wpdb->get_results( 113 "SELECT marketplace FROM {$wpdb->prefix}isarud_credentials WHERE is_active=1" 114 ); 115 62 $marketplaces = $wpdb->get_results("SELECT marketplace FROM {$wpdb->prefix}isarud_credentials WHERE is_active=1"); 116 63 $products_data = []; 117 64 $wc_products = wc_get_products(['status' => 'publish', 'limit' => 500]); 118 119 65 foreach ($wc_products as $product) { 120 $products_data[] = [ 121 'external_id' => (string)$product->get_id(), 122 'marketplace' => 'woocommerce', 123 'title' => $product->get_name(), 124 'sku' => $product->get_sku(), 125 'price' => (float)$product->get_price(), 126 'stock' => $product->get_stock_quantity() ?? 0, 127 'status' => $product->get_status(), 128 'image_url' => wp_get_attachment_url($product->get_image_id()) ?: null, 129 'meta' => [ 130 'barcode' => get_post_meta($product->get_id(), '_isarud_barcode', true), 131 'permalink' => $product->get_permalink(), 132 ], 133 ]; 134 66 $products_data[] = ['external_id' => (string)$product->get_id(), 'marketplace' => 'woocommerce', 'title' => $product->get_name(), 'sku' => $product->get_sku(), 'price' => (float)$product->get_price(), 'stock' => $product->get_stock_quantity() ?? 0, 'status' => $product->get_status(), 'image_url' => wp_get_attachment_url($product->get_image_id()) ?: null, 'meta' => ['barcode' => get_post_meta($product->get_id(), '_isarud_barcode', true), 'permalink' => $product->get_permalink()]]; 135 67 foreach ($marketplaces as $mp) { 136 68 $barcode = get_post_meta($product->get_id(), '_isarud_barcode', true) ?: $product->get_sku(); 137 69 if (empty($barcode)) continue; 138 139 $products_data[] = [ 140 'external_id' => $barcode, 141 'marketplace' => $mp->marketplace, 142 'title' => $product->get_name(), 143 'sku' => $product->get_sku(), 144 'price' => $this->apply_margin((float)$product->get_price(), $mp->marketplace), 145 'stock' => $product->get_stock_quantity() ?? 0, 146 'status' => $product->get_status(), 147 'image_url' => wp_get_attachment_url($product->get_image_id()) ?: null, 148 ]; 70 $products_data[] = ['external_id' => $barcode, 'marketplace' => $mp->marketplace, 'title' => $product->get_name(), 'sku' => $product->get_sku(), 'price' => $this->apply_margin((float)$product->get_price(), $mp->marketplace), 'stock' => $product->get_stock_quantity() ?? 0, 'status' => $product->get_status(), 'image_url' => wp_get_attachment_url($product->get_image_id()) ?: null]; 149 71 } 150 72 } 151 152 if (empty($products_data)) { 153 return ['success' => true, 'synced' => 0, 'message' => 'No products to sync']; 154 } 155 156 $total_synced = 0; 157 $total_failed = 0; 158 73 if (empty($products_data)) return ['success' => true, 'synced' => 0, 'message' => 'No products to sync']; 74 $total_synced = 0; $total_failed = 0; 159 75 foreach (array_chunk($products_data, 100) as $chunk) { 160 76 $result = $this->api_request('products/sync', ['products' => $chunk]); 161 if (isset($result['error'])) { 162 $total_failed += count($chunk); 163 } else { 164 $total_synced += $result['synced'] ?? 0; 165 $total_failed += $result['failed'] ?? 0; 166 } 167 } 168 77 if (isset($result['error'])) $total_failed += count($chunk); else { $total_synced += $result['synced'] ?? 0; $total_failed += $result['failed'] ?? 0; } 78 } 169 79 update_option('isarud_cloud_last_product_sync', current_time('mysql')); 170 171 return [ 172 'success' => true, 173 'synced' => $total_synced, 174 'failed' => $total_failed, 175 ]; 80 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 176 81 } 177 82 178 83 public function sync_orders(): array { 179 if (!$this->is_enabled() || !class_exists('WooCommerce')) { 180 return ['error' => 'Cloud sync not enabled']; 181 } 182 84 if (!$this->is_enabled() || !class_exists('WooCommerce')) return ['error' => 'Cloud sync not enabled']; 183 85 $last_sync = get_option('isarud_cloud_last_order_sync', '2000-01-01 00:00:00'); 184 185 $orders = wc_get_orders([ 186 'date_created' => '>' . strtotime($last_sync), 187 'limit' => 500, 188 'orderby' => 'date', 189 'order' => 'ASC', 190 ]); 191 192 if (empty($orders)) { 193 return ['success' => true, 'synced' => 0, 'message' => 'No new orders']; 194 } 195 86 $orders = wc_get_orders(['date_created' => '>' . strtotime($last_sync), 'limit' => 500, 'orderby' => 'date', 'order' => 'ASC']); 87 if (empty($orders)) return ['success' => true, 'synced' => 0, 'message' => 'No new orders']; 196 88 $orders_data = []; 197 foreach ($orders as $order) { 198 $orders_data[] = $this->format_order($order); 199 } 200 201 $total_synced = 0; 202 $total_failed = 0; 203 89 foreach ($orders as $order) $orders_data[] = $this->format_order($order); 90 $total_synced = 0; $total_failed = 0; 204 91 foreach (array_chunk($orders_data, 100) as $chunk) { 205 92 $result = $this->api_request('orders/sync', ['orders' => $chunk]); 206 if (isset($result['error'])) { 207 $total_failed += count($chunk); 208 } else { 209 $total_synced += $result['synced'] ?? 0; 210 $total_failed += $result['failed'] ?? 0; 211 } 212 } 213 93 if (isset($result['error'])) $total_failed += count($chunk); else { $total_synced += $result['synced'] ?? 0; $total_failed += $result['failed'] ?? 0; } 94 } 214 95 update_option('isarud_cloud_last_order_sync', current_time('mysql')); 215 216 return [ 217 'success' => true, 218 'synced' => $total_synced, 219 'failed' => $total_failed, 220 ]; 96 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 221 97 } 222 98 223 99 public function sync_order_to_cloud(int $order_id): void { 224 100 if (!$this->is_enabled()) return; 225 226 101 $order = wc_get_order($order_id); 227 102 if (!$order) return; 228 229 $this->api_request('orders/sync', [ 230 'orders' => [$this->format_order($order)], 231 ]); 103 $this->api_request('orders/sync', ['orders' => [$this->format_order($order)]]); 232 104 } 233 105 234 106 private function format_order($order): array { 235 return [ 236 'external_id' => (string)$order->get_id(), 237 'marketplace' => 'woocommerce', 238 'customer_name' => trim($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()), 239 'customer_email' => $order->get_billing_email(), 240 'total' => (float)$order->get_total(), 241 'currency' => $order->get_currency(), 242 'status' => $order->get_status(), 243 'order_date' => $order->get_date_created()?->format('Y-m-d H:i:s'), 244 'meta' => [ 245 'billing_country' => $order->get_billing_country(), 246 'shipping_country' => $order->get_shipping_country(), 247 'payment_method' => $order->get_payment_method(), 248 'items_count' => $order->get_item_count(), 249 ], 250 ]; 251 } 252 253 /** 254 * Sync extended data: settings, customers, abandoned carts, einvoices 255 */ 107 return ['external_id' => (string)$order->get_id(), 'marketplace' => 'woocommerce', 'customer_name' => trim($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()), 'customer_email' => $order->get_billing_email(), 'total' => (float)$order->get_total(), 'currency' => $order->get_currency(), 'status' => $order->get_status(), 'order_date' => $order->get_date_created()?->format('Y-m-d H:i:s'), 'meta' => ['billing_country' => $order->get_billing_country(), 'shipping_country' => $order->get_shipping_country(), 'payment_method' => $order->get_payment_method(), 'items_count' => $order->get_item_count()]]; 108 } 109 256 110 public function sync_extended_data(): array { 257 if (!$this->is_enabled()) { 258 return ['error' => 'Cloud sync not enabled']; 259 } 260 111 if (!$this->is_enabled()) return ['error' => 'Cloud sync not enabled']; 261 112 $results = []; 262 263 113 $results['settings'] = $this->sync_settings(); 264 114 $results['customers'] = $this->sync_customers(); 265 115 $results['abandoned_carts'] = $this->sync_abandoned_carts(); 266 116 $results['einvoices'] = $this->sync_einvoices(); 267 117 $results['credentials'] = $this->sync_credentials(); 118 $results['screening_logs'] = $this->sync_screening_logs(); 119 $results['sync_logs'] = $this->sync_sync_logs(); 120 $results['suppliers'] = $this->sync_suppliers(); 121 $results['affiliates'] = $this->sync_affiliates(); 268 122 update_option('isarud_cloud_last_extended_sync', current_time('mysql')); 269 270 123 return $results; 271 124 } 272 125 273 126 private function sync_settings(): array { 274 $option_keys = [ 275 'isarud_b2b_settings', 276 'isarud_currency_settings', 277 'isarud_tcmb_rates', 278 'isarud_segment_settings', 279 'isarud_einvoice_settings', 280 'isarud_popup_settings', 281 'isarud_popup_campaigns', 282 'isarud_cart_recovery_settings', 283 'isarud_email_marketing_settings', 284 'isarud_email_log', 285 'isarud_upsell_settings', 286 'isarud_upsell_rules', 287 ]; 288 127 $option_keys = ['isarud_b2b_settings', 'isarud_currency_settings', 'isarud_tcmb_rates', 'isarud_segment_settings', 'isarud_einvoice_settings', 'isarud_popup_settings', 'isarud_popup_campaigns', 'isarud_cart_recovery_settings', 'isarud_email_marketing_settings', 'isarud_email_log', 'isarud_upsell_settings', 'isarud_upsell_rules', 'isarud_api_key', 'isarud_auto_screen', 'isarud_block_match', 'isarud_alert_email', 'isarud_webhook_secret', 'isarud_auto_import_orders', 'isarud_category_mappings']; 289 128 $settings = []; 290 129 foreach ($option_keys as $key) { 291 130 $value = get_option($key, null); 292 if ($value !== null) { 293 $settings[] = [ 294 'key' => $key, 295 'value' => is_array($value) ? $value : json_decode($value, true), 296 ]; 131 if ($value !== null && $value !== false) { 132 $settings[] = ['key' => $key, 'value' => is_array($value) ? $value : (is_string($value) ? (json_decode($value, true) ?? $value) : $value)]; 297 133 } 298 134 } 299 300 if (empty($settings)) { 301 return ['success' => true, 'synced' => 0, 'message' => 'No settings to sync']; 302 } 303 304 $result = $this->api_request('settings/sync', ['settings' => $settings]); 305 306 return $result; 135 if (empty($settings)) return ['success' => true, 'synced' => 0, 'message' => 'No settings to sync']; 136 return $this->api_request('settings/sync', ['settings' => $settings]); 307 137 } 308 138 309 139 private function sync_customers(): array { 310 if (!class_exists('WooCommerce')) { 311 return ['success' => true, 'synced' => 0, 'message' => 'WooCommerce not active']; 312 } 313 140 if (!class_exists('WooCommerce')) return ['success' => true, 'synced' => 0]; 314 141 $segment_settings = get_option('isarud_segment_settings', []); 315 142 $b2b_settings = get_option('isarud_b2b_settings', []); 316 317 $customers_query = new \WC_Customer_Query([ 318 'limit' => 500, 319 'orderby' => 'date_created', 320 'order' => 'DESC', 321 ]); 322 323 $wc_customers = $customers_query->get_customers(); 324 325 if (empty($wc_customers)) { 326 return ['success' => true, 'synced' => 0, 'message' => 'No customers']; 327 } 328 143 $wc_customers = (new \WC_Customer_Query(['limit' => 500, 'orderby' => 'date_created', 'order' => 'DESC']))->get_customers(); 144 if (empty($wc_customers)) return ['success' => true, 'synced' => 0]; 329 145 $customers_data = []; 330 146 foreach ($wc_customers as $customer) { 331 $customer_id = $customer->get_id(); 332 $order_count = (int)$customer->get_order_count(); 333 $total_spent = (float)$customer->get_total_spent(); 334 335 $segment = $this->determine_segment($customer_id, $order_count, $total_spent, $segment_settings); 336 337 $b2b_discount = 0; 338 $company = $customer->get_billing_company(); 339 if (!empty($b2b_settings['enabled']) && $b2b_settings['enabled'] === 'yes') { 340 $b2b_discount = (float)get_user_meta($customer_id, '_isarud_b2b_discount', true); 341 } 342 343 $customers_data[] = [ 344 'external_id' => $customer_id, 345 'email' => $customer->get_email(), 346 'name' => trim($customer->get_first_name() . ' ' . $customer->get_last_name()), 347 'company' => $company ?: null, 348 'segment' => $segment, 349 'discount_rate' => $b2b_discount, 350 'total_orders' => $order_count, 351 'total_spent' => $total_spent, 352 'meta' => [ 353 'billing_country' => $customer->get_billing_country(), 354 'billing_city' => $customer->get_billing_city(), 355 'phone' => $customer->get_billing_phone(), 356 'date_created' => $customer->get_date_created() ? $customer->get_date_created()->format('Y-m-d H:i:s') : null, 357 ], 358 ]; 359 } 360 361 $total_synced = 0; 362 $total_failed = 0; 363 364 foreach (array_chunk($customers_data, 100) as $chunk) { 365 $result = $this->api_request('customers/sync', ['customers' => $chunk]); 366 if (isset($result['error'])) { 367 $total_failed += count($chunk); 368 } else { 369 $total_synced += $result['synced'] ?? 0; 370 $total_failed += $result['failed'] ?? 0; 371 } 372 } 373 374 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 375 } 376 377 private function determine_segment(int $customer_id, int $order_count, float $total_spent, array $settings): string { 378 $vip_threshold = (float)($settings['vip_min_spent'] ?? 5000); 379 $loyal_threshold = (int)($settings['loyal_min_orders'] ?? 5); 380 $risk_days = (int)($settings['risk_inactive_days'] ?? 180); 381 382 if ($total_spent >= $vip_threshold) return 'vip'; 383 if ($order_count >= $loyal_threshold) return 'loyal'; 384 if ($order_count === 1) return 'one_time'; 385 if ($order_count === 0) return 'new'; 386 387 $last_order_date = get_user_meta($customer_id, '_last_order_date', true); 388 if ($last_order_date) { 389 $days_since = (int)((time() - strtotime($last_order_date)) / 86400); 390 if ($days_since > $risk_days) return 'churned'; 391 if ($days_since > ($risk_days / 2)) return 'at_risk'; 392 } 393 147 $cid = $customer->get_id(); $oc = (int)$customer->get_order_count(); $ts = (float)$customer->get_total_spent(); 148 $b2b_discount = (!empty($b2b_settings['enabled']) && $b2b_settings['enabled'] === 'yes') ? (float)get_user_meta($cid, '_isarud_b2b_discount', true) : 0; 149 $customers_data[] = ['external_id' => $cid, 'email' => $customer->get_email(), 'name' => trim($customer->get_first_name() . ' ' . $customer->get_last_name()), 'company' => $customer->get_billing_company() ?: null, 'segment' => $this->determine_segment($cid, $oc, $ts, $segment_settings), 'discount_rate' => $b2b_discount, 'total_orders' => $oc, 'total_spent' => $ts, 'meta' => ['billing_country' => $customer->get_billing_country(), 'billing_city' => $customer->get_billing_city(), 'phone' => $customer->get_billing_phone(), 'date_created' => $customer->get_date_created() ? $customer->get_date_created()->format('Y-m-d H:i:s') : null]]; 150 } 151 $ts2 = 0; $tf2 = 0; 152 foreach (array_chunk($customers_data, 100) as $chunk) { $r = $this->api_request('customers/sync', ['customers' => $chunk]); if (isset($r['error'])) $tf2 += count($chunk); else { $ts2 += $r['synced'] ?? 0; $tf2 += $r['failed'] ?? 0; } } 153 return ['success' => true, 'synced' => $ts2, 'failed' => $tf2]; 154 } 155 156 private function determine_segment(int $cid, int $oc, float $ts, array $s): string { 157 $vip = (float)($s['vip_min_spent'] ?? 5000); $loyal = (int)($s['loyal_min_orders'] ?? 5); $risk = (int)($s['risk_inactive_days'] ?? 180); 158 if ($ts >= $vip) return 'vip'; if ($oc >= $loyal) return 'loyal'; if ($oc === 1) return 'one_time'; if ($oc === 0) return 'new'; 159 $ld = get_user_meta($cid, '_last_order_date', true); 160 if ($ld) { $ds = (int)((time() - strtotime($ld)) / 86400); if ($ds > $risk) return 'churned'; if ($ds > ($risk / 2)) return 'at_risk'; } 394 161 return 'regular'; 395 162 } 396 163 397 164 private function sync_abandoned_carts(): array { 398 global $wpdb; 399 $table = $wpdb->prefix . 'isarud_abandoned_carts'; 400 401 if ($wpdb->get_var("SHOW TABLES LIKE '{$table}'") !== $table) { 402 return ['success' => true, 'synced' => 0, 'message' => 'Abandoned carts table not found']; 403 } 404 405 $carts = $wpdb->get_results("SELECT * FROM {$table} ORDER BY updated_at DESC LIMIT 500"); 406 407 if (empty($carts)) { 408 return ['success' => true, 'synced' => 0, 'message' => 'No abandoned carts']; 409 } 410 411 $carts_data = []; 412 foreach ($carts as $cart) { 413 $cart_items = maybe_unserialize($cart->cart_contents ?? ''); 414 if (is_string($cart_items)) { 415 $cart_items = json_decode($cart_items, true); 416 } 417 418 $carts_data[] = [ 419 'external_id' => (int)$cart->id, 420 'session_id' => $cart->session_id ?? null, 421 'email' => $cart->email ?? null, 422 'customer_name' => $cart->customer_name ?? null, 423 'cart_total' => (float)($cart->cart_total ?? 0), 424 'cart_items' => is_array($cart_items) ? $cart_items : null, 425 'status' => $cart->status ?? 'abandoned', 426 'emails_sent' => (int)($cart->emails_sent ?? 0), 427 'last_email_at' => $cart->last_email_at ?? null, 428 'recovered_at' => $cart->recovered_at ?? null, 429 'cart_date' => $cart->created_at ?? $cart->updated_at ?? null, 430 ]; 431 } 432 433 $total_synced = 0; 434 $total_failed = 0; 435 436 foreach (array_chunk($carts_data, 100) as $chunk) { 437 $result = $this->api_request('abandoned-carts/sync', ['carts' => $chunk]); 438 if (isset($result['error'])) { 439 $total_failed += count($chunk); 440 } else { 441 $total_synced += $result['synced'] ?? 0; 442 $total_failed += $result['failed'] ?? 0; 443 } 444 } 445 446 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 165 global $wpdb; $t = $wpdb->prefix . 'isarud_abandoned_carts'; 166 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0, 'message' => 'Table not found']; 167 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY updated_at DESC LIMIT 500"); 168 if (empty($rows)) return ['success' => true, 'synced' => 0]; 169 $data = []; 170 foreach ($rows as $r) { $ci = maybe_unserialize($r->cart_contents ?? ''); if (is_string($ci)) $ci = json_decode($ci, true); $data[] = ['external_id' => (int)$r->id, 'session_id' => $r->session_id ?? null, 'email' => $r->email ?? null, 'customer_name' => $r->customer_name ?? null, 'cart_total' => (float)($r->cart_total ?? 0), 'cart_items' => is_array($ci) ? $ci : null, 'status' => $r->status ?? 'abandoned', 'emails_sent' => (int)($r->emails_sent ?? 0), 'last_email_at' => $r->last_email_at ?? null, 'recovered_at' => $r->recovered_at ?? null, 'cart_date' => $r->created_at ?? $r->updated_at ?? null]; } 171 $ts = 0; $tf = 0; 172 foreach (array_chunk($data, 100) as $chunk) { $res = $this->api_request('abandoned-carts/sync', ['carts' => $chunk]); if (isset($res['error'])) $tf += count($chunk); else { $ts += $res['synced'] ?? 0; $tf += $res['failed'] ?? 0; } } 173 return ['success' => true, 'synced' => $ts, 'failed' => $tf]; 447 174 } 448 175 449 176 private function sync_einvoices(): array { 450 global $wpdb; 451 $table = $wpdb->prefix . 'isarud_einvoices'; 452 453 if ($wpdb->get_var("SHOW TABLES LIKE '{$table}'") !== $table) { 454 return ['success' => true, 'synced' => 0, 'message' => 'Einvoices table not found']; 455 } 456 457 $invoices = $wpdb->get_results("SELECT * FROM {$table} ORDER BY created_at DESC LIMIT 500"); 458 459 if (empty($invoices)) { 460 return ['success' => true, 'synced' => 0, 'message' => 'No einvoices']; 461 } 462 463 $invoices_data = []; 464 foreach ($invoices as $inv) { 465 $gib_response = $inv->gib_response ?? null; 466 if (is_string($gib_response)) { 467 $gib_response = json_decode($gib_response, true); 468 } 469 470 $invoices_data[] = [ 471 'external_id' => (int)$inv->id, 472 'order_id' => (int)($inv->order_id ?? 0), 473 'invoice_number' => $inv->invoice_number ?? null, 474 'invoice_type' => $inv->invoice_type ?? 'einvoice', 475 'customer_name' => $inv->customer_name ?? null, 476 'customer_tax_id' => $inv->tax_id ?? $inv->customer_tax_id ?? null, 477 'total' => (float)($inv->total ?? 0), 478 'currency' => $inv->currency ?? 'TRY', 479 'status' => $inv->status ?? 'draft', 480 'gib_response' => is_array($gib_response) ? $gib_response : null, 481 'invoice_date' => $inv->invoice_date ?? $inv->created_at ?? null, 482 ]; 483 } 484 485 $total_synced = 0; 486 $total_failed = 0; 487 488 foreach (array_chunk($invoices_data, 100) as $chunk) { 489 $result = $this->api_request('einvoices/sync', ['einvoices' => $chunk]); 490 if (isset($result['error'])) { 491 $total_failed += count($chunk); 492 } else { 493 $total_synced += $result['synced'] ?? 0; 494 $total_failed += $result['failed'] ?? 0; 495 } 496 } 497 498 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 499 } 500 501 /** 502 * Run full cloud sync (products + orders + extended) — called by cron 503 */ 177 global $wpdb; $t = $wpdb->prefix . 'isarud_einvoices'; 178 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0, 'message' => 'Table not found']; 179 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY created_at DESC LIMIT 500"); 180 if (empty($rows)) return ['success' => true, 'synced' => 0]; 181 $data = []; 182 foreach ($rows as $r) { $gr = $r->gib_response ?? null; if (is_string($gr)) $gr = json_decode($gr, true); $data[] = ['external_id' => (int)$r->id, 'order_id' => (int)($r->order_id ?? 0), 'invoice_number' => $r->invoice_number ?? null, 'invoice_type' => $r->invoice_type ?? 'einvoice', 'customer_name' => $r->customer_name ?? null, 'customer_tax_id' => $r->tax_id ?? $r->customer_tax_id ?? null, 'total' => (float)($r->total ?? 0), 'currency' => $r->currency ?? 'TRY', 'status' => $r->status ?? 'draft', 'gib_response' => is_array($gr) ? $gr : null, 'invoice_date' => $r->invoice_date ?? $r->created_at ?? null]; } 183 $ts = 0; $tf = 0; 184 foreach (array_chunk($data, 100) as $chunk) { $res = $this->api_request('einvoices/sync', ['einvoices' => $chunk]); if (isset($res['error'])) $tf += count($chunk); else { $ts += $res['synced'] ?? 0; $tf += $res['failed'] ?? 0; } } 185 return ['success' => true, 'synced' => $ts, 'failed' => $tf]; 186 } 187 188 private function sync_credentials(): array { 189 global $wpdb; $rows = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}isarud_credentials ORDER BY id ASC"); 190 if (empty($rows)) return ['success' => true, 'synced' => 0]; 191 $data = []; 192 foreach ($rows as $r) $data[] = ['marketplace' => $r->marketplace, 'is_active' => (bool)$r->is_active, 'price_margin' => (float)$r->price_margin, 'price_margin_type' => $r->price_margin_type ?? 'percent', 'auto_sync' => (bool)$r->auto_sync, 'sync_interval' => $r->sync_interval ?? 'daily', 'last_test' => $r->last_test, 'test_status' => $r->test_status, 'last_sync' => $r->last_sync]; 193 return $this->api_request('credentials/sync', ['credentials' => $data]); 194 } 195 196 private function sync_screening_logs(): array { 197 global $wpdb; $t = $wpdb->prefix . 'isarud_screening_log'; 198 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0]; 199 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY created_at DESC LIMIT 500"); 200 if (empty($rows)) return ['success' => true, 'synced' => 0]; 201 $data = []; 202 foreach ($rows as $r) { $ns = is_string($r->names_screened) ? json_decode($r->names_screened, true) : $r->names_screened; $rs = is_string($r->results) ? json_decode($r->results, true) : $r->results; $data[] = ['external_id' => (int)$r->id, 'order_id' => (int)($r->order_id ?? 0), 'names_screened' => is_array($ns) ? $ns : null, 'has_match' => (bool)($r->has_match ?? false), 'results' => is_array($rs) ? $rs : null, 'created_at' => $r->created_at]; } 203 $ts = 0; $tf = 0; 204 foreach (array_chunk($data, 100) as $chunk) { $res = $this->api_request('screening-logs/sync', ['logs' => $chunk]); if (isset($res['error'])) $tf += count($chunk); else { $ts += $res['synced'] ?? 0; $tf += $res['failed'] ?? 0; } } 205 return ['success' => true, 'synced' => $ts, 'failed' => $tf]; 206 } 207 208 private function sync_sync_logs(): array { 209 global $wpdb; $t = $wpdb->prefix . 'isarud_sync_log'; 210 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0]; 211 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY created_at DESC LIMIT 500"); 212 if (empty($rows)) return ['success' => true, 'synced' => 0]; 213 $data = []; 214 foreach ($rows as $r) $data[] = ['external_id' => (int)$r->id, 'product_id' => (int)($r->product_id ?? 0), 'marketplace' => $r->marketplace ?? null, 'action' => $r->action ?? null, 'status' => $r->status ?? null, 'message' => $r->message ?? null, 'created_at' => $r->created_at]; 215 $ts = 0; $tf = 0; 216 foreach (array_chunk($data, 100) as $chunk) { $res = $this->api_request('sync-logs/sync', ['logs' => $chunk]); if (isset($res['error'])) $tf += count($chunk); else { $ts += $res['synced'] ?? 0; $tf += $res['failed'] ?? 0; } } 217 return ['success' => true, 'synced' => $ts, 'failed' => $tf]; 218 } 219 220 private function sync_suppliers(): array { 221 global $wpdb; $t = $wpdb->prefix . 'isarud_dropship_suppliers'; 222 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0]; 223 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY id ASC"); 224 if (empty($rows)) return ['success' => true, 'synced' => 0]; 225 $data = []; 226 foreach ($rows as $r) $data[] = ['external_id' => (int)$r->id, 'name' => $r->name, 'email' => $r->email ?? null, 'api_url' => $r->api_url ?? null, 'auto_forward' => (bool)($r->auto_forward ?? false), 'commission_rate' => (float)($r->commission_rate ?? 0), 'is_active' => (bool)($r->is_active ?? true)]; 227 return $this->api_request('suppliers/sync', ['suppliers' => $data]); 228 } 229 230 private function sync_affiliates(): array { 231 global $wpdb; $t = $wpdb->prefix . 'isarud_affiliates'; 232 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0]; 233 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY id ASC"); 234 if (empty($rows)) return ['success' => true, 'synced' => 0]; 235 $data = []; 236 foreach ($rows as $r) $data[] = ['external_id' => (int)$r->id, 'name' => $r->name, 'email' => $r->email ?? null, 'code' => $r->code ?? null, 'commission_rate' => (float)($r->commission_rate ?? 10), 'total_sales' => (float)($r->total_sales ?? 0), 'total_commission' => (float)($r->total_commission ?? 0), 'is_active' => (bool)($r->is_active ?? true)]; 237 return $this->api_request('affiliates/sync', ['affiliates' => $data]); 238 } 239 504 240 public function run_cloud_sync(): void { 505 241 if (!$this->is_enabled()) return; 506 507 $this->sync_products(); 508 $this->sync_orders(); 509 $this->sync_extended_data(); 510 242 $this->sync_products(); $this->sync_orders(); $this->sync_extended_data(); 511 243 update_option('isarud_cloud_last_sync', current_time('mysql')); 512 244 } 513 245 514 /**515 * Manual trigger for extended sync only516 */517 246 public function run_extended_sync_now(): array { 518 if (!$this->is_enabled()) { 519 return ['error' => 'Cloud sync not enabled']; 520 } 521 247 if (!$this->is_enabled()) return ['error' => 'Cloud sync not enabled']; 522 248 return $this->sync_extended_data(); 523 249 } 524 250 525 251 private function apply_margin(float $price, string $mp): float { 526 $plugin = Isarud_Plugin::instance(); 527 if (method_exists($plugin, 'sync_stock_public')) { 528 global $wpdb; 529 $row = $wpdb->get_row($wpdb->prepare( 530 "SELECT price_margin, price_margin_type FROM {$wpdb->prefix}isarud_credentials WHERE marketplace=%s", 531 $mp 532 )); 533 if ($row && floatval($row->price_margin) != 0) { 534 return $row->price_margin_type === 'percent' 535 ? round($price * (1 + floatval($row->price_margin) / 100), 2) 536 : round($price + floatval($row->price_margin), 2); 537 } 538 } 252 global $wpdb; 253 $row = $wpdb->get_row($wpdb->prepare("SELECT price_margin, price_margin_type FROM {$wpdb->prefix}isarud_credentials WHERE marketplace=%s", $mp)); 254 if ($row && floatval($row->price_margin) != 0) return $row->price_margin_type === 'percent' ? round($price * (1 + floatval($row->price_margin) / 100), 2) : round($price + floatval($row->price_margin), 2); 539 255 return $price; 540 256 } 541 257 542 258 public function get_status(): array { 543 return [ 544 'enabled' => $this->is_enabled(), 545 'cloud_key' => !empty($this->get_cloud_key()) ? '••••' . substr($this->get_cloud_key(), -8) : '', 546 'last_sync' => get_option('isarud_cloud_last_sync', ''), 547 'last_product_sync' => get_option('isarud_cloud_last_product_sync', ''), 548 'last_order_sync' => get_option('isarud_cloud_last_order_sync', ''), 549 'last_extended_sync' => get_option('isarud_cloud_last_extended_sync', ''), 550 ]; 259 return ['enabled' => $this->is_enabled(), 'cloud_key' => !empty($this->get_cloud_key()) ? '••••' . substr($this->get_cloud_key(), -8) : '', 'last_sync' => get_option('isarud_cloud_last_sync', ''), 'last_product_sync' => get_option('isarud_cloud_last_product_sync', ''), 'last_order_sync' => get_option('isarud_cloud_last_order_sync', ''), 'last_extended_sync' => get_option('isarud_cloud_last_extended_sync', '')]; 551 260 } 552 261 553 262 public function disconnect(): void { 554 delete_option('isarud_cloud_api_key'); 555 delete_option('isarud_cloud_enabled'); 556 delete_option('isarud_cloud_platform_id'); 557 delete_option('isarud_cloud_last_sync'); 558 delete_option('isarud_cloud_last_product_sync'); 559 delete_option('isarud_cloud_last_order_sync'); 560 delete_option('isarud_cloud_last_extended_sync'); 263 delete_option('isarud_cloud_api_key'); delete_option('isarud_cloud_enabled'); delete_option('isarud_cloud_platform_id'); 264 delete_option('isarud_cloud_last_sync'); delete_option('isarud_cloud_last_product_sync'); delete_option('isarud_cloud_last_order_sync'); delete_option('isarud_cloud_last_extended_sync'); 561 265 wp_clear_scheduled_hook('isarud_cloud_sync_hook'); 562 266 } -
api-isarud/tags/6.2.0/readme-tr_TR.txt
r3493435 r3493482 5 5 Tested up to: 6.9 6 6 Requires PHP: 8.0 7 Stable tag: 6. 1.07 Stable tag: 6.2.0 8 8 License: GPLv2 or later 9 9 -
api-isarud/tags/6.2.0/readme.txt
r3493435 r3493482 5 5 Tested up to: 6.9 6 6 Requires PHP: 8.0 7 Stable tag: 6. 1.07 Stable tag: 6.2.0 8 8 License: GPLv2 or later 9 9 -
api-isarud/trunk/api-isarud.php
r3493435 r3493482 17 17 if (!defined('ABSPATH')) exit; 18 18 19 define('ISARUD_VERSION', '6. 1.0');19 define('ISARUD_VERSION', '6.2.0'); 20 20 define('ISARUD_DIR', plugin_dir_path(__FILE__)); 21 21 define('ISARUD_URL', plugin_dir_url(__FILE__)); -
api-isarud/trunk/isarud-cloud-sync.php
r3493435 r3493482 2 2 /** 3 3 * Isarud Cloud Sync — isarud.com API v2 entegrasyonu 4 * WP Plugin v6. 1.04 * WP Plugin v6.2.0 5 5 */ 6 6 if (!defined('ABSPATH')) exit; … … 19 19 add_action('isarud_cloud_sync_hook', [$this, 'run_cloud_sync']); 20 20 add_action('woocommerce_new_order', [$this, 'sync_order_to_cloud'], 40, 1); 21 22 21 if (get_option('isarud_cloud_enabled') === 'yes') { 23 22 if (!wp_next_scheduled('isarud_cloud_sync_hook')) { … … 27 26 } 28 27 29 private function get_cloud_key(): string { 30 return get_option('isarud_cloud_api_key', ''); 31 } 32 33 public function is_enabled(): bool { 34 return get_option('isarud_cloud_enabled') === 'yes' && !empty($this->get_cloud_key()); 35 } 28 private function get_cloud_key(): string { return get_option('isarud_cloud_api_key', ''); } 29 public function is_enabled(): bool { return get_option('isarud_cloud_enabled') === 'yes' && !empty($this->get_cloud_key()); } 36 30 37 31 private function api_request(string $endpoint, array $data = [], string $method = 'POST'): array { 38 32 $key = $this->get_cloud_key(); 39 33 if (empty($key)) return ['error' => 'Cloud API key not configured']; 40 41 $args = [ 42 'method' => $method, 43 'timeout' => 30, 44 'headers' => [ 45 'Content-Type' => 'application/json', 46 'X-Marketplace-Key' => $key, 47 'User-Agent' => 'IsarudWP/' . ISARUD_VERSION, 48 ], 49 ]; 50 51 if (!empty($data) && in_array($method, ['POST', 'PUT'])) { 52 $args['body'] = wp_json_encode($data); 53 } 54 34 $args = ['method' => $method, 'timeout' => 30, 'headers' => ['Content-Type' => 'application/json', 'X-Marketplace-Key' => $key, 'User-Agent' => 'IsarudWP/' . ISARUD_VERSION]]; 35 if (!empty($data) && in_array($method, ['POST', 'PUT'])) $args['body'] = wp_json_encode($data); 55 36 $response = wp_remote_request($this->api_base . $endpoint, $args); 56 57 if (is_wp_error($response)) { 58 return ['error' => $response->get_error_message()]; 59 } 60 37 if (is_wp_error($response)) return ['error' => $response->get_error_message()]; 61 38 $code = wp_remote_retrieve_response_code($response); 62 39 $body = json_decode(wp_remote_retrieve_body($response), true) ?: []; 63 64 if ($code >= 400) { 65 return ['error' => $body['error'] ?? "HTTP {$code}"]; 66 } 67 40 if ($code >= 400) return ['error' => $body['error'] ?? "HTTP {$code}"]; 68 41 return $body; 69 42 } 70 43 71 44 public function connect_site(string $bearer_token): array { 72 $response = wp_remote_post('https://isarud.com/api/v2/marketplace/connect', [ 73 'timeout' => 30, 74 'headers' => [ 75 'Content-Type' => 'application/json', 76 'Authorization' => 'Bearer ' . $bearer_token, 77 ], 78 'body' => wp_json_encode([ 79 'platform' => 'wordpress', 80 'site_url' => home_url(), 81 'site_name' => get_bloginfo('name'), 82 ]), 83 ]); 84 85 if (is_wp_error($response)) { 86 return ['error' => $response->get_error_message()]; 87 } 88 45 $response = wp_remote_post('https://isarud.com/api/v2/marketplace/connect', ['timeout' => 30, 'headers' => ['Content-Type' => 'application/json', 'Authorization' => 'Bearer ' . $bearer_token], 'body' => wp_json_encode(['platform' => 'wordpress', 'site_url' => home_url(), 'site_name' => get_bloginfo('name')])]); 46 if (is_wp_error($response)) return ['error' => $response->get_error_message()]; 89 47 $body = json_decode(wp_remote_retrieve_body($response), true) ?: []; 90 91 48 if (!empty($body['success']) && !empty($body['platform']['api_key'])) { 92 49 update_option('isarud_cloud_api_key', $body['platform']['api_key']); … … 96 53 return ['success' => true, 'message' => 'Connected to isarud.com']; 97 54 } 98 99 if (isset($body['error']) && strpos($body['error'], 'already connected') !== false) { 100 return ['success' => true, 'message' => 'Already connected']; 101 } 102 55 if (isset($body['error']) && strpos($body['error'], 'already connected') !== false) return ['success' => true, 'message' => 'Already connected']; 103 56 return ['error' => $body['error'] ?? 'Connection failed']; 104 57 } 105 58 106 59 public function sync_products(): array { 107 if (!$this->is_enabled() || !class_exists('WooCommerce')) { 108 return ['error' => 'Cloud sync not enabled or WooCommerce not active']; 109 } 110 60 if (!$this->is_enabled() || !class_exists('WooCommerce')) return ['error' => 'Cloud sync not enabled or WooCommerce not active']; 111 61 global $wpdb; 112 $marketplaces = $wpdb->get_results( 113 "SELECT marketplace FROM {$wpdb->prefix}isarud_credentials WHERE is_active=1" 114 ); 115 62 $marketplaces = $wpdb->get_results("SELECT marketplace FROM {$wpdb->prefix}isarud_credentials WHERE is_active=1"); 116 63 $products_data = []; 117 64 $wc_products = wc_get_products(['status' => 'publish', 'limit' => 500]); 118 119 65 foreach ($wc_products as $product) { 120 $products_data[] = [ 121 'external_id' => (string)$product->get_id(), 122 'marketplace' => 'woocommerce', 123 'title' => $product->get_name(), 124 'sku' => $product->get_sku(), 125 'price' => (float)$product->get_price(), 126 'stock' => $product->get_stock_quantity() ?? 0, 127 'status' => $product->get_status(), 128 'image_url' => wp_get_attachment_url($product->get_image_id()) ?: null, 129 'meta' => [ 130 'barcode' => get_post_meta($product->get_id(), '_isarud_barcode', true), 131 'permalink' => $product->get_permalink(), 132 ], 133 ]; 134 66 $products_data[] = ['external_id' => (string)$product->get_id(), 'marketplace' => 'woocommerce', 'title' => $product->get_name(), 'sku' => $product->get_sku(), 'price' => (float)$product->get_price(), 'stock' => $product->get_stock_quantity() ?? 0, 'status' => $product->get_status(), 'image_url' => wp_get_attachment_url($product->get_image_id()) ?: null, 'meta' => ['barcode' => get_post_meta($product->get_id(), '_isarud_barcode', true), 'permalink' => $product->get_permalink()]]; 135 67 foreach ($marketplaces as $mp) { 136 68 $barcode = get_post_meta($product->get_id(), '_isarud_barcode', true) ?: $product->get_sku(); 137 69 if (empty($barcode)) continue; 138 139 $products_data[] = [ 140 'external_id' => $barcode, 141 'marketplace' => $mp->marketplace, 142 'title' => $product->get_name(), 143 'sku' => $product->get_sku(), 144 'price' => $this->apply_margin((float)$product->get_price(), $mp->marketplace), 145 'stock' => $product->get_stock_quantity() ?? 0, 146 'status' => $product->get_status(), 147 'image_url' => wp_get_attachment_url($product->get_image_id()) ?: null, 148 ]; 70 $products_data[] = ['external_id' => $barcode, 'marketplace' => $mp->marketplace, 'title' => $product->get_name(), 'sku' => $product->get_sku(), 'price' => $this->apply_margin((float)$product->get_price(), $mp->marketplace), 'stock' => $product->get_stock_quantity() ?? 0, 'status' => $product->get_status(), 'image_url' => wp_get_attachment_url($product->get_image_id()) ?: null]; 149 71 } 150 72 } 151 152 if (empty($products_data)) { 153 return ['success' => true, 'synced' => 0, 'message' => 'No products to sync']; 154 } 155 156 $total_synced = 0; 157 $total_failed = 0; 158 73 if (empty($products_data)) return ['success' => true, 'synced' => 0, 'message' => 'No products to sync']; 74 $total_synced = 0; $total_failed = 0; 159 75 foreach (array_chunk($products_data, 100) as $chunk) { 160 76 $result = $this->api_request('products/sync', ['products' => $chunk]); 161 if (isset($result['error'])) { 162 $total_failed += count($chunk); 163 } else { 164 $total_synced += $result['synced'] ?? 0; 165 $total_failed += $result['failed'] ?? 0; 166 } 167 } 168 77 if (isset($result['error'])) $total_failed += count($chunk); else { $total_synced += $result['synced'] ?? 0; $total_failed += $result['failed'] ?? 0; } 78 } 169 79 update_option('isarud_cloud_last_product_sync', current_time('mysql')); 170 171 return [ 172 'success' => true, 173 'synced' => $total_synced, 174 'failed' => $total_failed, 175 ]; 80 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 176 81 } 177 82 178 83 public function sync_orders(): array { 179 if (!$this->is_enabled() || !class_exists('WooCommerce')) { 180 return ['error' => 'Cloud sync not enabled']; 181 } 182 84 if (!$this->is_enabled() || !class_exists('WooCommerce')) return ['error' => 'Cloud sync not enabled']; 183 85 $last_sync = get_option('isarud_cloud_last_order_sync', '2000-01-01 00:00:00'); 184 185 $orders = wc_get_orders([ 186 'date_created' => '>' . strtotime($last_sync), 187 'limit' => 500, 188 'orderby' => 'date', 189 'order' => 'ASC', 190 ]); 191 192 if (empty($orders)) { 193 return ['success' => true, 'synced' => 0, 'message' => 'No new orders']; 194 } 195 86 $orders = wc_get_orders(['date_created' => '>' . strtotime($last_sync), 'limit' => 500, 'orderby' => 'date', 'order' => 'ASC']); 87 if (empty($orders)) return ['success' => true, 'synced' => 0, 'message' => 'No new orders']; 196 88 $orders_data = []; 197 foreach ($orders as $order) { 198 $orders_data[] = $this->format_order($order); 199 } 200 201 $total_synced = 0; 202 $total_failed = 0; 203 89 foreach ($orders as $order) $orders_data[] = $this->format_order($order); 90 $total_synced = 0; $total_failed = 0; 204 91 foreach (array_chunk($orders_data, 100) as $chunk) { 205 92 $result = $this->api_request('orders/sync', ['orders' => $chunk]); 206 if (isset($result['error'])) { 207 $total_failed += count($chunk); 208 } else { 209 $total_synced += $result['synced'] ?? 0; 210 $total_failed += $result['failed'] ?? 0; 211 } 212 } 213 93 if (isset($result['error'])) $total_failed += count($chunk); else { $total_synced += $result['synced'] ?? 0; $total_failed += $result['failed'] ?? 0; } 94 } 214 95 update_option('isarud_cloud_last_order_sync', current_time('mysql')); 215 216 return [ 217 'success' => true, 218 'synced' => $total_synced, 219 'failed' => $total_failed, 220 ]; 96 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 221 97 } 222 98 223 99 public function sync_order_to_cloud(int $order_id): void { 224 100 if (!$this->is_enabled()) return; 225 226 101 $order = wc_get_order($order_id); 227 102 if (!$order) return; 228 229 $this->api_request('orders/sync', [ 230 'orders' => [$this->format_order($order)], 231 ]); 103 $this->api_request('orders/sync', ['orders' => [$this->format_order($order)]]); 232 104 } 233 105 234 106 private function format_order($order): array { 235 return [ 236 'external_id' => (string)$order->get_id(), 237 'marketplace' => 'woocommerce', 238 'customer_name' => trim($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()), 239 'customer_email' => $order->get_billing_email(), 240 'total' => (float)$order->get_total(), 241 'currency' => $order->get_currency(), 242 'status' => $order->get_status(), 243 'order_date' => $order->get_date_created()?->format('Y-m-d H:i:s'), 244 'meta' => [ 245 'billing_country' => $order->get_billing_country(), 246 'shipping_country' => $order->get_shipping_country(), 247 'payment_method' => $order->get_payment_method(), 248 'items_count' => $order->get_item_count(), 249 ], 250 ]; 251 } 252 253 /** 254 * Sync extended data: settings, customers, abandoned carts, einvoices 255 */ 107 return ['external_id' => (string)$order->get_id(), 'marketplace' => 'woocommerce', 'customer_name' => trim($order->get_billing_first_name() . ' ' . $order->get_billing_last_name()), 'customer_email' => $order->get_billing_email(), 'total' => (float)$order->get_total(), 'currency' => $order->get_currency(), 'status' => $order->get_status(), 'order_date' => $order->get_date_created()?->format('Y-m-d H:i:s'), 'meta' => ['billing_country' => $order->get_billing_country(), 'shipping_country' => $order->get_shipping_country(), 'payment_method' => $order->get_payment_method(), 'items_count' => $order->get_item_count()]]; 108 } 109 256 110 public function sync_extended_data(): array { 257 if (!$this->is_enabled()) { 258 return ['error' => 'Cloud sync not enabled']; 259 } 260 111 if (!$this->is_enabled()) return ['error' => 'Cloud sync not enabled']; 261 112 $results = []; 262 263 113 $results['settings'] = $this->sync_settings(); 264 114 $results['customers'] = $this->sync_customers(); 265 115 $results['abandoned_carts'] = $this->sync_abandoned_carts(); 266 116 $results['einvoices'] = $this->sync_einvoices(); 267 117 $results['credentials'] = $this->sync_credentials(); 118 $results['screening_logs'] = $this->sync_screening_logs(); 119 $results['sync_logs'] = $this->sync_sync_logs(); 120 $results['suppliers'] = $this->sync_suppliers(); 121 $results['affiliates'] = $this->sync_affiliates(); 268 122 update_option('isarud_cloud_last_extended_sync', current_time('mysql')); 269 270 123 return $results; 271 124 } 272 125 273 126 private function sync_settings(): array { 274 $option_keys = [ 275 'isarud_b2b_settings', 276 'isarud_currency_settings', 277 'isarud_tcmb_rates', 278 'isarud_segment_settings', 279 'isarud_einvoice_settings', 280 'isarud_popup_settings', 281 'isarud_popup_campaigns', 282 'isarud_cart_recovery_settings', 283 'isarud_email_marketing_settings', 284 'isarud_email_log', 285 'isarud_upsell_settings', 286 'isarud_upsell_rules', 287 ]; 288 127 $option_keys = ['isarud_b2b_settings', 'isarud_currency_settings', 'isarud_tcmb_rates', 'isarud_segment_settings', 'isarud_einvoice_settings', 'isarud_popup_settings', 'isarud_popup_campaigns', 'isarud_cart_recovery_settings', 'isarud_email_marketing_settings', 'isarud_email_log', 'isarud_upsell_settings', 'isarud_upsell_rules', 'isarud_api_key', 'isarud_auto_screen', 'isarud_block_match', 'isarud_alert_email', 'isarud_webhook_secret', 'isarud_auto_import_orders', 'isarud_category_mappings']; 289 128 $settings = []; 290 129 foreach ($option_keys as $key) { 291 130 $value = get_option($key, null); 292 if ($value !== null) { 293 $settings[] = [ 294 'key' => $key, 295 'value' => is_array($value) ? $value : json_decode($value, true), 296 ]; 131 if ($value !== null && $value !== false) { 132 $settings[] = ['key' => $key, 'value' => is_array($value) ? $value : (is_string($value) ? (json_decode($value, true) ?? $value) : $value)]; 297 133 } 298 134 } 299 300 if (empty($settings)) { 301 return ['success' => true, 'synced' => 0, 'message' => 'No settings to sync']; 302 } 303 304 $result = $this->api_request('settings/sync', ['settings' => $settings]); 305 306 return $result; 135 if (empty($settings)) return ['success' => true, 'synced' => 0, 'message' => 'No settings to sync']; 136 return $this->api_request('settings/sync', ['settings' => $settings]); 307 137 } 308 138 309 139 private function sync_customers(): array { 310 if (!class_exists('WooCommerce')) { 311 return ['success' => true, 'synced' => 0, 'message' => 'WooCommerce not active']; 312 } 313 140 if (!class_exists('WooCommerce')) return ['success' => true, 'synced' => 0]; 314 141 $segment_settings = get_option('isarud_segment_settings', []); 315 142 $b2b_settings = get_option('isarud_b2b_settings', []); 316 317 $customers_query = new \WC_Customer_Query([ 318 'limit' => 500, 319 'orderby' => 'date_created', 320 'order' => 'DESC', 321 ]); 322 323 $wc_customers = $customers_query->get_customers(); 324 325 if (empty($wc_customers)) { 326 return ['success' => true, 'synced' => 0, 'message' => 'No customers']; 327 } 328 143 $wc_customers = (new \WC_Customer_Query(['limit' => 500, 'orderby' => 'date_created', 'order' => 'DESC']))->get_customers(); 144 if (empty($wc_customers)) return ['success' => true, 'synced' => 0]; 329 145 $customers_data = []; 330 146 foreach ($wc_customers as $customer) { 331 $customer_id = $customer->get_id(); 332 $order_count = (int)$customer->get_order_count(); 333 $total_spent = (float)$customer->get_total_spent(); 334 335 $segment = $this->determine_segment($customer_id, $order_count, $total_spent, $segment_settings); 336 337 $b2b_discount = 0; 338 $company = $customer->get_billing_company(); 339 if (!empty($b2b_settings['enabled']) && $b2b_settings['enabled'] === 'yes') { 340 $b2b_discount = (float)get_user_meta($customer_id, '_isarud_b2b_discount', true); 341 } 342 343 $customers_data[] = [ 344 'external_id' => $customer_id, 345 'email' => $customer->get_email(), 346 'name' => trim($customer->get_first_name() . ' ' . $customer->get_last_name()), 347 'company' => $company ?: null, 348 'segment' => $segment, 349 'discount_rate' => $b2b_discount, 350 'total_orders' => $order_count, 351 'total_spent' => $total_spent, 352 'meta' => [ 353 'billing_country' => $customer->get_billing_country(), 354 'billing_city' => $customer->get_billing_city(), 355 'phone' => $customer->get_billing_phone(), 356 'date_created' => $customer->get_date_created() ? $customer->get_date_created()->format('Y-m-d H:i:s') : null, 357 ], 358 ]; 359 } 360 361 $total_synced = 0; 362 $total_failed = 0; 363 364 foreach (array_chunk($customers_data, 100) as $chunk) { 365 $result = $this->api_request('customers/sync', ['customers' => $chunk]); 366 if (isset($result['error'])) { 367 $total_failed += count($chunk); 368 } else { 369 $total_synced += $result['synced'] ?? 0; 370 $total_failed += $result['failed'] ?? 0; 371 } 372 } 373 374 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 375 } 376 377 private function determine_segment(int $customer_id, int $order_count, float $total_spent, array $settings): string { 378 $vip_threshold = (float)($settings['vip_min_spent'] ?? 5000); 379 $loyal_threshold = (int)($settings['loyal_min_orders'] ?? 5); 380 $risk_days = (int)($settings['risk_inactive_days'] ?? 180); 381 382 if ($total_spent >= $vip_threshold) return 'vip'; 383 if ($order_count >= $loyal_threshold) return 'loyal'; 384 if ($order_count === 1) return 'one_time'; 385 if ($order_count === 0) return 'new'; 386 387 $last_order_date = get_user_meta($customer_id, '_last_order_date', true); 388 if ($last_order_date) { 389 $days_since = (int)((time() - strtotime($last_order_date)) / 86400); 390 if ($days_since > $risk_days) return 'churned'; 391 if ($days_since > ($risk_days / 2)) return 'at_risk'; 392 } 393 147 $cid = $customer->get_id(); $oc = (int)$customer->get_order_count(); $ts = (float)$customer->get_total_spent(); 148 $b2b_discount = (!empty($b2b_settings['enabled']) && $b2b_settings['enabled'] === 'yes') ? (float)get_user_meta($cid, '_isarud_b2b_discount', true) : 0; 149 $customers_data[] = ['external_id' => $cid, 'email' => $customer->get_email(), 'name' => trim($customer->get_first_name() . ' ' . $customer->get_last_name()), 'company' => $customer->get_billing_company() ?: null, 'segment' => $this->determine_segment($cid, $oc, $ts, $segment_settings), 'discount_rate' => $b2b_discount, 'total_orders' => $oc, 'total_spent' => $ts, 'meta' => ['billing_country' => $customer->get_billing_country(), 'billing_city' => $customer->get_billing_city(), 'phone' => $customer->get_billing_phone(), 'date_created' => $customer->get_date_created() ? $customer->get_date_created()->format('Y-m-d H:i:s') : null]]; 150 } 151 $ts2 = 0; $tf2 = 0; 152 foreach (array_chunk($customers_data, 100) as $chunk) { $r = $this->api_request('customers/sync', ['customers' => $chunk]); if (isset($r['error'])) $tf2 += count($chunk); else { $ts2 += $r['synced'] ?? 0; $tf2 += $r['failed'] ?? 0; } } 153 return ['success' => true, 'synced' => $ts2, 'failed' => $tf2]; 154 } 155 156 private function determine_segment(int $cid, int $oc, float $ts, array $s): string { 157 $vip = (float)($s['vip_min_spent'] ?? 5000); $loyal = (int)($s['loyal_min_orders'] ?? 5); $risk = (int)($s['risk_inactive_days'] ?? 180); 158 if ($ts >= $vip) return 'vip'; if ($oc >= $loyal) return 'loyal'; if ($oc === 1) return 'one_time'; if ($oc === 0) return 'new'; 159 $ld = get_user_meta($cid, '_last_order_date', true); 160 if ($ld) { $ds = (int)((time() - strtotime($ld)) / 86400); if ($ds > $risk) return 'churned'; if ($ds > ($risk / 2)) return 'at_risk'; } 394 161 return 'regular'; 395 162 } 396 163 397 164 private function sync_abandoned_carts(): array { 398 global $wpdb; 399 $table = $wpdb->prefix . 'isarud_abandoned_carts'; 400 401 if ($wpdb->get_var("SHOW TABLES LIKE '{$table}'") !== $table) { 402 return ['success' => true, 'synced' => 0, 'message' => 'Abandoned carts table not found']; 403 } 404 405 $carts = $wpdb->get_results("SELECT * FROM {$table} ORDER BY updated_at DESC LIMIT 500"); 406 407 if (empty($carts)) { 408 return ['success' => true, 'synced' => 0, 'message' => 'No abandoned carts']; 409 } 410 411 $carts_data = []; 412 foreach ($carts as $cart) { 413 $cart_items = maybe_unserialize($cart->cart_contents ?? ''); 414 if (is_string($cart_items)) { 415 $cart_items = json_decode($cart_items, true); 416 } 417 418 $carts_data[] = [ 419 'external_id' => (int)$cart->id, 420 'session_id' => $cart->session_id ?? null, 421 'email' => $cart->email ?? null, 422 'customer_name' => $cart->customer_name ?? null, 423 'cart_total' => (float)($cart->cart_total ?? 0), 424 'cart_items' => is_array($cart_items) ? $cart_items : null, 425 'status' => $cart->status ?? 'abandoned', 426 'emails_sent' => (int)($cart->emails_sent ?? 0), 427 'last_email_at' => $cart->last_email_at ?? null, 428 'recovered_at' => $cart->recovered_at ?? null, 429 'cart_date' => $cart->created_at ?? $cart->updated_at ?? null, 430 ]; 431 } 432 433 $total_synced = 0; 434 $total_failed = 0; 435 436 foreach (array_chunk($carts_data, 100) as $chunk) { 437 $result = $this->api_request('abandoned-carts/sync', ['carts' => $chunk]); 438 if (isset($result['error'])) { 439 $total_failed += count($chunk); 440 } else { 441 $total_synced += $result['synced'] ?? 0; 442 $total_failed += $result['failed'] ?? 0; 443 } 444 } 445 446 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 165 global $wpdb; $t = $wpdb->prefix . 'isarud_abandoned_carts'; 166 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0, 'message' => 'Table not found']; 167 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY updated_at DESC LIMIT 500"); 168 if (empty($rows)) return ['success' => true, 'synced' => 0]; 169 $data = []; 170 foreach ($rows as $r) { $ci = maybe_unserialize($r->cart_contents ?? ''); if (is_string($ci)) $ci = json_decode($ci, true); $data[] = ['external_id' => (int)$r->id, 'session_id' => $r->session_id ?? null, 'email' => $r->email ?? null, 'customer_name' => $r->customer_name ?? null, 'cart_total' => (float)($r->cart_total ?? 0), 'cart_items' => is_array($ci) ? $ci : null, 'status' => $r->status ?? 'abandoned', 'emails_sent' => (int)($r->emails_sent ?? 0), 'last_email_at' => $r->last_email_at ?? null, 'recovered_at' => $r->recovered_at ?? null, 'cart_date' => $r->created_at ?? $r->updated_at ?? null]; } 171 $ts = 0; $tf = 0; 172 foreach (array_chunk($data, 100) as $chunk) { $res = $this->api_request('abandoned-carts/sync', ['carts' => $chunk]); if (isset($res['error'])) $tf += count($chunk); else { $ts += $res['synced'] ?? 0; $tf += $res['failed'] ?? 0; } } 173 return ['success' => true, 'synced' => $ts, 'failed' => $tf]; 447 174 } 448 175 449 176 private function sync_einvoices(): array { 450 global $wpdb; 451 $table = $wpdb->prefix . 'isarud_einvoices'; 452 453 if ($wpdb->get_var("SHOW TABLES LIKE '{$table}'") !== $table) { 454 return ['success' => true, 'synced' => 0, 'message' => 'Einvoices table not found']; 455 } 456 457 $invoices = $wpdb->get_results("SELECT * FROM {$table} ORDER BY created_at DESC LIMIT 500"); 458 459 if (empty($invoices)) { 460 return ['success' => true, 'synced' => 0, 'message' => 'No einvoices']; 461 } 462 463 $invoices_data = []; 464 foreach ($invoices as $inv) { 465 $gib_response = $inv->gib_response ?? null; 466 if (is_string($gib_response)) { 467 $gib_response = json_decode($gib_response, true); 468 } 469 470 $invoices_data[] = [ 471 'external_id' => (int)$inv->id, 472 'order_id' => (int)($inv->order_id ?? 0), 473 'invoice_number' => $inv->invoice_number ?? null, 474 'invoice_type' => $inv->invoice_type ?? 'einvoice', 475 'customer_name' => $inv->customer_name ?? null, 476 'customer_tax_id' => $inv->tax_id ?? $inv->customer_tax_id ?? null, 477 'total' => (float)($inv->total ?? 0), 478 'currency' => $inv->currency ?? 'TRY', 479 'status' => $inv->status ?? 'draft', 480 'gib_response' => is_array($gib_response) ? $gib_response : null, 481 'invoice_date' => $inv->invoice_date ?? $inv->created_at ?? null, 482 ]; 483 } 484 485 $total_synced = 0; 486 $total_failed = 0; 487 488 foreach (array_chunk($invoices_data, 100) as $chunk) { 489 $result = $this->api_request('einvoices/sync', ['einvoices' => $chunk]); 490 if (isset($result['error'])) { 491 $total_failed += count($chunk); 492 } else { 493 $total_synced += $result['synced'] ?? 0; 494 $total_failed += $result['failed'] ?? 0; 495 } 496 } 497 498 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 499 } 500 501 /** 502 * Run full cloud sync (products + orders + extended) — called by cron 503 */ 177 global $wpdb; $t = $wpdb->prefix . 'isarud_einvoices'; 178 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0, 'message' => 'Table not found']; 179 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY created_at DESC LIMIT 500"); 180 if (empty($rows)) return ['success' => true, 'synced' => 0]; 181 $data = []; 182 foreach ($rows as $r) { $gr = $r->gib_response ?? null; if (is_string($gr)) $gr = json_decode($gr, true); $data[] = ['external_id' => (int)$r->id, 'order_id' => (int)($r->order_id ?? 0), 'invoice_number' => $r->invoice_number ?? null, 'invoice_type' => $r->invoice_type ?? 'einvoice', 'customer_name' => $r->customer_name ?? null, 'customer_tax_id' => $r->tax_id ?? $r->customer_tax_id ?? null, 'total' => (float)($r->total ?? 0), 'currency' => $r->currency ?? 'TRY', 'status' => $r->status ?? 'draft', 'gib_response' => is_array($gr) ? $gr : null, 'invoice_date' => $r->invoice_date ?? $r->created_at ?? null]; } 183 $ts = 0; $tf = 0; 184 foreach (array_chunk($data, 100) as $chunk) { $res = $this->api_request('einvoices/sync', ['einvoices' => $chunk]); if (isset($res['error'])) $tf += count($chunk); else { $ts += $res['synced'] ?? 0; $tf += $res['failed'] ?? 0; } } 185 return ['success' => true, 'synced' => $ts, 'failed' => $tf]; 186 } 187 188 private function sync_credentials(): array { 189 global $wpdb; $rows = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}isarud_credentials ORDER BY id ASC"); 190 if (empty($rows)) return ['success' => true, 'synced' => 0]; 191 $data = []; 192 foreach ($rows as $r) $data[] = ['marketplace' => $r->marketplace, 'is_active' => (bool)$r->is_active, 'price_margin' => (float)$r->price_margin, 'price_margin_type' => $r->price_margin_type ?? 'percent', 'auto_sync' => (bool)$r->auto_sync, 'sync_interval' => $r->sync_interval ?? 'daily', 'last_test' => $r->last_test, 'test_status' => $r->test_status, 'last_sync' => $r->last_sync]; 193 return $this->api_request('credentials/sync', ['credentials' => $data]); 194 } 195 196 private function sync_screening_logs(): array { 197 global $wpdb; $t = $wpdb->prefix . 'isarud_screening_log'; 198 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0]; 199 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY created_at DESC LIMIT 500"); 200 if (empty($rows)) return ['success' => true, 'synced' => 0]; 201 $data = []; 202 foreach ($rows as $r) { $ns = is_string($r->names_screened) ? json_decode($r->names_screened, true) : $r->names_screened; $rs = is_string($r->results) ? json_decode($r->results, true) : $r->results; $data[] = ['external_id' => (int)$r->id, 'order_id' => (int)($r->order_id ?? 0), 'names_screened' => is_array($ns) ? $ns : null, 'has_match' => (bool)($r->has_match ?? false), 'results' => is_array($rs) ? $rs : null, 'created_at' => $r->created_at]; } 203 $ts = 0; $tf = 0; 204 foreach (array_chunk($data, 100) as $chunk) { $res = $this->api_request('screening-logs/sync', ['logs' => $chunk]); if (isset($res['error'])) $tf += count($chunk); else { $ts += $res['synced'] ?? 0; $tf += $res['failed'] ?? 0; } } 205 return ['success' => true, 'synced' => $ts, 'failed' => $tf]; 206 } 207 208 private function sync_sync_logs(): array { 209 global $wpdb; $t = $wpdb->prefix . 'isarud_sync_log'; 210 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0]; 211 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY created_at DESC LIMIT 500"); 212 if (empty($rows)) return ['success' => true, 'synced' => 0]; 213 $data = []; 214 foreach ($rows as $r) $data[] = ['external_id' => (int)$r->id, 'product_id' => (int)($r->product_id ?? 0), 'marketplace' => $r->marketplace ?? null, 'action' => $r->action ?? null, 'status' => $r->status ?? null, 'message' => $r->message ?? null, 'created_at' => $r->created_at]; 215 $ts = 0; $tf = 0; 216 foreach (array_chunk($data, 100) as $chunk) { $res = $this->api_request('sync-logs/sync', ['logs' => $chunk]); if (isset($res['error'])) $tf += count($chunk); else { $ts += $res['synced'] ?? 0; $tf += $res['failed'] ?? 0; } } 217 return ['success' => true, 'synced' => $ts, 'failed' => $tf]; 218 } 219 220 private function sync_suppliers(): array { 221 global $wpdb; $t = $wpdb->prefix . 'isarud_dropship_suppliers'; 222 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0]; 223 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY id ASC"); 224 if (empty($rows)) return ['success' => true, 'synced' => 0]; 225 $data = []; 226 foreach ($rows as $r) $data[] = ['external_id' => (int)$r->id, 'name' => $r->name, 'email' => $r->email ?? null, 'api_url' => $r->api_url ?? null, 'auto_forward' => (bool)($r->auto_forward ?? false), 'commission_rate' => (float)($r->commission_rate ?? 0), 'is_active' => (bool)($r->is_active ?? true)]; 227 return $this->api_request('suppliers/sync', ['suppliers' => $data]); 228 } 229 230 private function sync_affiliates(): array { 231 global $wpdb; $t = $wpdb->prefix . 'isarud_affiliates'; 232 if ($wpdb->get_var("SHOW TABLES LIKE '{$t}'") !== $t) return ['success' => true, 'synced' => 0]; 233 $rows = $wpdb->get_results("SELECT * FROM {$t} ORDER BY id ASC"); 234 if (empty($rows)) return ['success' => true, 'synced' => 0]; 235 $data = []; 236 foreach ($rows as $r) $data[] = ['external_id' => (int)$r->id, 'name' => $r->name, 'email' => $r->email ?? null, 'code' => $r->code ?? null, 'commission_rate' => (float)($r->commission_rate ?? 10), 'total_sales' => (float)($r->total_sales ?? 0), 'total_commission' => (float)($r->total_commission ?? 0), 'is_active' => (bool)($r->is_active ?? true)]; 237 return $this->api_request('affiliates/sync', ['affiliates' => $data]); 238 } 239 504 240 public function run_cloud_sync(): void { 505 241 if (!$this->is_enabled()) return; 506 507 $this->sync_products(); 508 $this->sync_orders(); 509 $this->sync_extended_data(); 510 242 $this->sync_products(); $this->sync_orders(); $this->sync_extended_data(); 511 243 update_option('isarud_cloud_last_sync', current_time('mysql')); 512 244 } 513 245 514 /**515 * Manual trigger for extended sync only516 */517 246 public function run_extended_sync_now(): array { 518 if (!$this->is_enabled()) { 519 return ['error' => 'Cloud sync not enabled']; 520 } 521 247 if (!$this->is_enabled()) return ['error' => 'Cloud sync not enabled']; 522 248 return $this->sync_extended_data(); 523 249 } 524 250 525 251 private function apply_margin(float $price, string $mp): float { 526 $plugin = Isarud_Plugin::instance(); 527 if (method_exists($plugin, 'sync_stock_public')) { 528 global $wpdb; 529 $row = $wpdb->get_row($wpdb->prepare( 530 "SELECT price_margin, price_margin_type FROM {$wpdb->prefix}isarud_credentials WHERE marketplace=%s", 531 $mp 532 )); 533 if ($row && floatval($row->price_margin) != 0) { 534 return $row->price_margin_type === 'percent' 535 ? round($price * (1 + floatval($row->price_margin) / 100), 2) 536 : round($price + floatval($row->price_margin), 2); 537 } 538 } 252 global $wpdb; 253 $row = $wpdb->get_row($wpdb->prepare("SELECT price_margin, price_margin_type FROM {$wpdb->prefix}isarud_credentials WHERE marketplace=%s", $mp)); 254 if ($row && floatval($row->price_margin) != 0) return $row->price_margin_type === 'percent' ? round($price * (1 + floatval($row->price_margin) / 100), 2) : round($price + floatval($row->price_margin), 2); 539 255 return $price; 540 256 } 541 257 542 258 public function get_status(): array { 543 return [ 544 'enabled' => $this->is_enabled(), 545 'cloud_key' => !empty($this->get_cloud_key()) ? '••••' . substr($this->get_cloud_key(), -8) : '', 546 'last_sync' => get_option('isarud_cloud_last_sync', ''), 547 'last_product_sync' => get_option('isarud_cloud_last_product_sync', ''), 548 'last_order_sync' => get_option('isarud_cloud_last_order_sync', ''), 549 'last_extended_sync' => get_option('isarud_cloud_last_extended_sync', ''), 550 ]; 259 return ['enabled' => $this->is_enabled(), 'cloud_key' => !empty($this->get_cloud_key()) ? '••••' . substr($this->get_cloud_key(), -8) : '', 'last_sync' => get_option('isarud_cloud_last_sync', ''), 'last_product_sync' => get_option('isarud_cloud_last_product_sync', ''), 'last_order_sync' => get_option('isarud_cloud_last_order_sync', ''), 'last_extended_sync' => get_option('isarud_cloud_last_extended_sync', '')]; 551 260 } 552 261 553 262 public function disconnect(): void { 554 delete_option('isarud_cloud_api_key'); 555 delete_option('isarud_cloud_enabled'); 556 delete_option('isarud_cloud_platform_id'); 557 delete_option('isarud_cloud_last_sync'); 558 delete_option('isarud_cloud_last_product_sync'); 559 delete_option('isarud_cloud_last_order_sync'); 560 delete_option('isarud_cloud_last_extended_sync'); 263 delete_option('isarud_cloud_api_key'); delete_option('isarud_cloud_enabled'); delete_option('isarud_cloud_platform_id'); 264 delete_option('isarud_cloud_last_sync'); delete_option('isarud_cloud_last_product_sync'); delete_option('isarud_cloud_last_order_sync'); delete_option('isarud_cloud_last_extended_sync'); 561 265 wp_clear_scheduled_hook('isarud_cloud_sync_hook'); 562 266 } -
api-isarud/trunk/readme-tr_TR.txt
r3493435 r3493482 5 5 Tested up to: 6.9 6 6 Requires PHP: 8.0 7 Stable tag: 6. 1.07 Stable tag: 6.2.0 8 8 License: GPLv2 or later 9 9 -
api-isarud/trunk/readme.txt
r3493435 r3493482 5 5 Tested up to: 6.9 6 6 Requires PHP: 8.0 7 Stable tag: 6. 1.07 Stable tag: 6.2.0 8 8 License: GPLv2 or later 9 9
Note: See TracChangeset
for help on using the changeset viewer.