Changeset 2735651
- Timestamp:
- 06/01/2022 12:46:53 PM (4 years ago)
- Location:
- sokan-integration
- Files:
-
- 18 added
- 3 edited
-
tags/1.5.2 (added)
-
tags/1.5.2/Sokan-integration.php (added)
-
tags/1.5.2/admin.php (added)
-
tags/1.5.2/assets (added)
-
tags/1.5.2/assets/images (added)
-
tags/1.5.2/assets/images/sokan-logo.png (added)
-
tags/1.5.2/include (added)
-
tags/1.5.2/include/classes (added)
-
tags/1.5.2/include/classes/class-skng-api.php (added)
-
tags/1.5.2/include/classes/class-skng-db.php (added)
-
tags/1.5.2/include/classes/class-skng-logger.php (added)
-
tags/1.5.2/include/custom (added)
-
tags/1.5.2/include/custom/skng-custom.php (added)
-
tags/1.5.2/index.php (added)
-
tags/1.5.2/job (added)
-
tags/1.5.2/job/sync_data.php (added)
-
tags/1.5.2/readme.txt (added)
-
tags/1.5.2/uninstall.php (added)
-
trunk/Sokan-integration.php (modified) (1 diff)
-
trunk/include/classes/class-skng-db.php (modified) (4 diffs)
-
trunk/readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sokan-integration/trunk/Sokan-integration.php
r2733673 r2735651 7 7 * Plugin Name: sokan Integration 8 8 * Description: افزونه ای برای استخراج تمامی اطلاعات ووکامرس مورد نیاز پلتفرم سکان 9 * Version: 1.5. 19 * Version: 1.5.2 10 10 * Author: Sokan 11 11 * Author URI: https://Sokan.tech/ -
sokan-integration/trunk/include/classes/class-skng-db.php
r2733685 r2735651 8 8 class Skng_Sokan_db { 9 9 10 /**11 * @var Wpdb12 * @since 1.1.013 */14 private wpdb $db;15 16 /**17 * array of filter for extract data from woocommerce tables18 * @var array19 * @since 1.2.020 */21 private array $filters;22 23 /**24 * array of customer and region key name for search in woocommerce tables25 * @var array26 * @since 1.2.027 */28 private array $order_attr = [29 'user_id' => '_customer_user',30 'first_name' => '_billing_first_name',31 'last_name' => '_billing_last_name',32 'city' => '_billing_city',33 'state' => '_billing_state',34 'country' => '_billing_country',35 'phone' => '_billing_phone',36 'email' => '_billing_email',37 ];38 39 /**40 * array of region Code and name for replacing41 * @var array42 * @since 1.2.043 */44 private array $states = array(45 'KHZ' => 'خوزستان',46 'THR' => 'تهران',47 'ILM' => 'ایلام',48 'BHR' => 'بوشهر',49 'ADL' => 'اردبیل',50 'ESF' => 'اصفهان',51 'YZD' => 'یزد',52 'KRH' => 'کرمانشاه',53 'KRN' => 'کرمان',54 'HDN' => 'همدان',55 'GZN' => 'قزوین',56 'ZJN' => 'زنجان',57 'LRS' => 'لرستان',58 'ABZ' => 'البرز',59 'EAZ' => 'آذربایجان شرقی',60 'WAZ' => 'آذربایجان غربی',61 'CHB' => 'چهارمحال و بختیاری',62 'SKH' => 'خراسان جنوبی',63 'RKH' => 'خراسان رضوی',64 'NKH' => 'خراسان شمالی',65 'SMN' => 'سمنان',66 'FRS' => 'فارس',67 'QHM' => 'قم',68 'KRD' => 'کردستان',69 'KBD' => 'کهگیلویه و بویراحمد',70 'GLS' => 'گلستان',71 'GIL' => 'گیلان',72 'MZN' => 'مازندران',73 'MKZ' => 'مرکزی',74 'HRZ' => 'هرمزگان',75 'SBN' => 'سیستان و بلوچستان',76 );77 78 public function __construct( $wpdp ) {79 $this->db = $wpdp;80 $this->filters = [81 'log_table' => "{$wpdp->prefix}" . SKNG_PLUGIN_NAME . "_logs",82 'update_date' => get_option( SKNG_PLUGIN_NAME . "_sync_date" ),83 'complete_status' => get_option( SKNG_PLUGIN_NAME . '_sale_status' ),84 'refunded_status' => get_option( SKNG_PLUGIN_NAME . '_refunded_status' ),85 'api_limitation' => get_option( SKNG_PLUGIN_NAME . '_api_limitation' ),86 'customer_identity' => get_option( SKNG_PLUGIN_NAME . '_customer_identity' )87 ];88 $this->order_attr = apply_filters( "skng_set_orders_attr", $this->order_attr );89 }90 91 /**92 * return all available sokan api urls93 * @return array94 * @since 1.2.095 */96 public function webServiceUrls(): array {97 return [98 'ارسال به نسخه آزمایشی' => "https://api-lab.sokan.tech/",99 'ارسال به نسخه دمو' => "https://api-demo.sokan.tech/",100 'ارسال به نسخه اپ' => "https://api-app.sokan.tech/",101 ];102 }103 104 /**105 * return all available customer identity value106 * @return array107 * @since 1.4.0108 */109 public function customerIdentities(): array {110 return [111 'شماره تلفن مشتریان' => "phone",112 'کد کاربری مشتریان' => "id",113 'نام و نام خانوادگی مشتریان' => "name",114 ];115 }116 117 /**118 * return all available sync mode119 * @return array120 * @since 1.4.0121 */122 public function syncModes(): array {123 return [124 'در پس زمینه (30 ثانیه بعد از تغییر وضعیت سفارش)' => "async",125 'همزمان با تغییر وضعیت سفارش' => "sync",126 ];127 }128 129 /**130 * reset last sync date and clear log table131 * @return void132 * @since 1.2.0133 */134 public function resetSyncDate() {135 $logTable = $this->filters['log_table'];136 update_option( SKNG_PLUGIN_NAME . '_sync_date', '' );137 $this->db->query( "TRUNCATE TABLE $logTable" );138 }139 140 /**141 * return all products and their brands and categories list142 *143 * @param $ids144 *145 * @return array146 * @since 1.3.0147 */148 public function getProducts( $ids ): array {149 $data = $this->db->get_results(150 "10 /** 11 * @var Wpdb 12 * @since 1.1.0 13 */ 14 private wpdb $db; 15 16 /** 17 * array of filter for extract data from woocommerce tables 18 * @var array 19 * @since 1.2.0 20 */ 21 private array $filters; 22 23 /** 24 * array of customer and region key name for search in woocommerce tables 25 * @var array 26 * @since 1.2.0 27 */ 28 private array $order_attr = [ 29 'user_id' => '_customer_user', 30 'first_name' => '_billing_first_name', 31 'last_name' => '_billing_last_name', 32 'city' => '_billing_city', 33 'state' => '_billing_state', 34 'country' => '_billing_country', 35 'phone' => '_billing_phone', 36 'email' => '_billing_email', 37 ]; 38 39 /** 40 * array of region Code and name for replacing 41 * @var array 42 * @since 1.2.0 43 */ 44 private array $states = array( 45 'KHZ' => 'خوزستان', 46 'THR' => 'تهران', 47 'ILM' => 'ایلام', 48 'BHR' => 'بوشهر', 49 'ADL' => 'اردبیل', 50 'ESF' => 'اصفهان', 51 'YZD' => 'یزد', 52 'KRH' => 'کرمانشاه', 53 'KRN' => 'کرمان', 54 'HDN' => 'همدان', 55 'GZN' => 'قزوین', 56 'ZJN' => 'زنجان', 57 'LRS' => 'لرستان', 58 'ABZ' => 'البرز', 59 'EAZ' => 'آذربایجان شرقی', 60 'WAZ' => 'آذربایجان غربی', 61 'CHB' => 'چهارمحال و بختیاری', 62 'SKH' => 'خراسان جنوبی', 63 'RKH' => 'خراسان رضوی', 64 'NKH' => 'خراسان شمالی', 65 'SMN' => 'سمنان', 66 'FRS' => 'فارس', 67 'QHM' => 'قم', 68 'KRD' => 'کردستان', 69 'KBD' => 'کهگیلویه و بویراحمد', 70 'GLS' => 'گلستان', 71 'GIL' => 'گیلان', 72 'MZN' => 'مازندران', 73 'MKZ' => 'مرکزی', 74 'HRZ' => 'هرمزگان', 75 'SBN' => 'سیستان و بلوچستان', 76 ); 77 78 public function __construct( $wpdp ) { 79 $this->db = $wpdp; 80 $this->filters = [ 81 'log_table' => "{$wpdp->prefix}" . SKNG_PLUGIN_NAME . "_logs", 82 'update_date' => get_option( SKNG_PLUGIN_NAME . "_sync_date" ), 83 'complete_status' => get_option( SKNG_PLUGIN_NAME . '_sale_status' ), 84 'refunded_status' => get_option( SKNG_PLUGIN_NAME . '_refunded_status' ), 85 'api_limitation' => get_option( SKNG_PLUGIN_NAME . '_api_limitation' ), 86 'customer_identity' => get_option( SKNG_PLUGIN_NAME . '_customer_identity' ) 87 ]; 88 $this->order_attr = apply_filters( "skng_set_orders_attr", $this->order_attr ); 89 } 90 91 /** 92 * return all available sokan api urls 93 * @return array 94 * @since 1.2.0 95 */ 96 public function webServiceUrls(): array { 97 return [ 98 'ارسال به نسخه آزمایشی' => "https://api-lab.sokan.tech/", 99 'ارسال به نسخه دمو' => "https://api-demo.sokan.tech/", 100 'ارسال به نسخه اپ' => "https://api-app.sokan.tech/", 101 ]; 102 } 103 104 /** 105 * return all available customer identity value 106 * @return array 107 * @since 1.4.0 108 */ 109 public function customerIdentities(): array { 110 return [ 111 'شماره تلفن مشتریان' => "phone", 112 'کد کاربری مشتریان' => "id", 113 'نام و نام خانوادگی مشتریان' => "name", 114 ]; 115 } 116 117 /** 118 * return all available sync mode 119 * @return array 120 * @since 1.4.0 121 */ 122 public function syncModes(): array { 123 return [ 124 'در پس زمینه (30 ثانیه بعد از تغییر وضعیت سفارش)' => "async", 125 'همزمان با تغییر وضعیت سفارش' => "sync", 126 ]; 127 } 128 129 /** 130 * reset last sync date and clear log table 131 * @return void 132 * @since 1.2.0 133 */ 134 public function resetSyncDate() { 135 $logTable = $this->filters['log_table']; 136 update_option( SKNG_PLUGIN_NAME . '_sync_date', '' ); 137 $this->db->query( "TRUNCATE TABLE $logTable" ); 138 } 139 140 /** 141 * return all products and their brands and categories list 142 * 143 * @param $ids 144 * 145 * @return array 146 * @since 1.3.0 147 */ 148 public function getProducts( $ids ): array { 149 $data = $this->db->get_results( 150 " 151 151 SELECT ID as id , post_title , 152 152 {$this->db->prefix}terms.term_id , … … 170 170 ORDER BY {$this->db->prefix}term_taxonomy.parent DESC 171 171 " 172 , ARRAY_A173 );174 175 $categories = $this->db->get_results(176 "172 , ARRAY_A 173 ); 174 175 $categories = $this->db->get_results( 176 " 177 177 SELECT * FROM `{$this->db->prefix}term_taxonomy` 178 178 JOIN `{$this->db->prefix}terms` … … 180 180 WHERE `{$this->db->prefix}term_taxonomy`.taxonomy = 'product_cat' 181 181 ", ARRAY_A 182 );183 184 $products = [];185 $categories_ids = array_column( $categories, 'term_id' );186 $data = apply_filters( "skng_before_validate_product_attr", $data );187 foreach ( $data as $item ) {188 $product_id = $item['id'];189 $products[ $product_id ]['name'] = $item['post_title'];190 if ( $item['taxonomy'] == 'product_cat' ) {191 if ( isset( $products[ $product_id ]['categories'] ) ) continue;192 193 $parent = $item['parent'];194 $cats = [ $item['name'] ];195 for ( $x = 0; $x <= 8; $x ++ ) {196 $key = array_search( $parent, $categories_ids );182 ); 183 184 $products = []; 185 $categories_ids = array_column( $categories, 'term_id' ); 186 $data = apply_filters( "skng_before_validate_product_attr", $data ); 187 foreach ( $data as $item ) { 188 $product_id = $item['id']; 189 $products[ $product_id ]['name'] = $item['post_title']; 190 if ( $item['taxonomy'] == 'product_cat' ) { 191 if ( isset( $products[ $product_id ]['categories'] ) ) continue; 192 193 $parent = $item['parent']; 194 $cats = [ $item['name'] ]; 195 for ( $x = 0; $x <= 8; $x ++ ) { 196 $key = array_search( $parent, $categories_ids ); 197 197 if ($key === false) break; 198 198 array_push( $cats, $categories[ $key ]['name'] ); 199 199 $parent = $categories[ $key ]['parent']; 200 }201 $products[ $product_id ]['categories'] = array_reverse( $cats );202 }203 if ( strpos( $item['taxonomy'], "brand" ) != false or strpos( $item['taxonomy'], "برند" ) != false ) {204 $products[ $product_id ]['brand'] = $item['name'];205 continue;206 }207 if ( strpos( $item['taxonomy'], "weight" ) != false or strpos( $item['taxonomy'], "وزن" ) != false ) {208 $products[ $product_id ]['weight'] = $item['name'];209 }210 }211 212 return apply_filters( "skng_get_all_product_filter", $products );213 }214 215 216 /**217 * return all deleted product names218 *219 * @param $ids220 *221 * @return array222 * @since 1.5.0223 */224 public function getDeletedProducts( $ids ): array {225 $ids = implode( "','", $ids );226 $products = $this->db->get_results(227 "SELECT * FROM `{$this->db->prefix}woocommerce_order_items`200 } 201 $products[ $product_id ]['categories'] = array_reverse( $cats ); 202 } 203 if ( strpos( $item['taxonomy'], "brand" ) != false or strpos( $item['taxonomy'], "برند" ) != false ) { 204 $products[ $product_id ]['brand'] = $item['name']; 205 continue; 206 } 207 if ( strpos( $item['taxonomy'], "weight" ) != false or strpos( $item['taxonomy'], "وزن" ) != false ) { 208 $products[ $product_id ]['weight'] = $item['name']; 209 } 210 } 211 212 return apply_filters( "skng_get_all_product_filter", $products ); 213 } 214 215 216 /** 217 * return all deleted product names 218 * 219 * @param $ids 220 * 221 * @return array 222 * @since 1.5.0 223 */ 224 public function getDeletedProducts( $ids ): array { 225 $ids = implode( "','", $ids ); 226 $products = $this->db->get_results( 227 "SELECT * FROM `{$this->db->prefix}woocommerce_order_items` 228 228 WHERE `{$this->db->prefix}woocommerce_order_items`.order_item_id 229 229 IN ('$ids')", 230 ARRAY_A231 );232 $result = [];233 foreach ( $products as $product ) {234 $result[ $product['order_item_id'] ] = $product['order_item_name'];235 }236 237 return $result;238 }239 240 /**241 * return all order based on filters242 * @return array invoices243 * return list of invoices244 * @since 1.1.0245 */246 public function getAllOrders(): array {247 $date = $this->filters['update_date'];248 $ref_status = $this->filters['refunded_status'];249 $customer_identity = $this->filters['customer_identity'];250 251 if ( count( $ids = $this->getAvailableOrderIds() ) == 0 ) {252 return [ 'order' => [], 'date' => $date ];253 }254 255 $all_invoices = $this->getOrderData( $ids );256 $new_orders = [];257 $product_ids = [];258 259 foreach ( $all_invoices as $order_key => $value ) {260 261 $date = $value['modified_date'] ?? $date;262 $order_date = $value['post_date'] ?? $date;263 $first_name = $value[ $this->order_attr['first_name'] ] ?? "مشتری";264 $last_name = $value[ $this->order_attr['last_name'] ] ?? "نامشخص";265 $customer_name = trim( trim( $first_name, " " ) . " " . trim( $last_name, " " ), " " );266 $customer_phone = $this->convertToEnNumbers( $value[ $this->order_attr['phone'] ] ?? "" );267 268 if ( preg_match( '/^(?:98|\+98|0098|0|\+980|00980)?9[0-9]{9}/', $customer_phone, $_phone, PREG_OFFSET_CAPTURE ) ) {269 $_phone = $_phone[0][0];270 $_phone = str_replace( "+980", '+98', $_phone );271 $_phone = str_replace( "00980", '+98', $_phone );272 $customer_phone = preg_replace( '/^(?:98|\+98|0098|0)/', "0", $_phone );273 }274 275 $customer_id = $value[ $this->order_attr['user_id'] ] ?? ( empty( $customer_phone ) ? $customer_name : $customer_phone );276 277 if ( $customer_identity == 'phone' and ! empty( $customer_phone ) ) {278 $customer_id = trim( str_replace( "0", "", $customer_phone ), " " );279 } elseif ( $customer_identity == 'name' and $customer_name != "مشتری نامشخص" ) {280 $customer_id = $customer_name;281 } elseif ( $customer_id == 0 ) {282 $customer_id = $customer_name != "مشتری نامشخص" ? $customer_name : $order_key;283 }284 285 $state = $value[ $this->order_attr['state'] ] ?? "نامشخص";286 $city = $value[ $this->order_attr['city'] ] ?? "نامشخص";287 288 if ( ! isset( $value['items'] ) and isset( $value['_order_total'] ) ) {289 $value['items'][ $value['_order_total'] ]['_fee_amount'] = $value['_order_total'];290 } elseif ( ! isset( $value['items'] ) ) {291 continue;292 }293 294 foreach ( $value['items'] as $item_key => $item ) {295 296 $qty = $item['_qty'] ?? 1;297 $qty = abs( $qty );298 $discount = 0;299 $unit_price = 0;300 $total = 0;301 $product_id = 'Undefined Product';302 $product_type = 'SERVICE';303 304 if ( isset( $item['_line_subtotal'] ) ) {305 306 if ( $item['_line_subtotal'] > 0 ) {307 $unit_price = $item['_line_subtotal'] / $qty;308 } else {309 $unit_price = $item['_line_total'] / $qty;310 }311 if ( $item['_line_total'] != 0 ) {312 $total = $item['_line_total'] / $qty;313 }314 $discount = ( $unit_price - $total ) * $qty;315 $product_type = 'PRODUCT';316 317 if ( ! empty( $item['_product_id'] ) ) {318 $product_id = $item['_product_id'];319 $product_ids[ $product_id ] = $product_id;320 }321 } else if ( isset( $item['cost'] ) ) {322 323 $unit_price = (int) $item['cost'];324 $product_id = 'هزینه ارسال';325 326 } else if ( isset( $item['_fee_amount'] ) ) {327 $unit_price = (int) $item['_fee_amount'];328 }329 330 $weight = $item['pa_weight'] ?? 0;331 332 $order = [333 'item_id' => (string) $item_key,334 'invoice_id' => (string) $order_key,335 'date' => (string) $order_date,336 'unit_price' => abs( (int) $unit_price ),337 'type' => "SALES",338 'quantity' => (int) $qty,339 'discount' => (int) $discount,340 'weight' => (int) $weight,341 'customer_id' => $customer_id,342 'customer_name' => $customer_name,343 'region0' => "ایران",344 'region1' => $this->getRegionName( $state ),345 'region2' => $this->getRegionName( $city),346 'sku_id' => $product_id,347 'product_name' => $product_id,348 'product_type' => $product_type349 ];350 351 if ( preg_match( '/^(?:98|\+98|0098|0)?9[0-9]{9}$/', $customer_phone ) ) {352 $order['customer_phone_number'] = $customer_phone;353 }354 355 array_push( $new_orders, $order );356 357 if ( $value['status'] == $ref_status ) {358 $refund_order = $order;359 $refund_order['item_id'] = $refund_order['item_id'] . "_refunded";360 $refund_order['quantity'] = - $refund_order['quantity'];361 $refund_order['discount'] = - $refund_order['discount'];362 $refund_order['type'] = "RETURN";363 array_push( $new_orders, $refund_order );364 }365 }366 }367 368 $all_products = $this->getProducts( $product_ids );369 $order_ids = [];370 foreach ( $new_orders as $key => $order_item ) {371 372 if ( isset( $all_products[ $order_item['sku_id'] ] ) ) {373 374 $product = $all_products[ $order_item['sku_id'] ];375 $new_orders[ $key ]['product_name'] = $product['name'];376 377 if ( isset( $product['brand'] ) ) {378 $new_orders[ $key ]['product_brand0'] = $product['brand'];379 }380 if ( isset( $product['categories'] ) ) {381 foreach ( $product['categories'] as $cat_key => $name ) {382 $new_orders[ $key ][ 'product_category' . $cat_key ] = $name;383 }384 }385 if ( $order_item['weight'] == 0 and isset( $product['weight'] ) ) {386 $new_orders[ $key ]['weight'] = (int) $product['weight'];387 }388 } elseif ( $order_item['sku_id'] == 'Undefined Product' and $order_item['sku_id'] != 'هزینه ارسال' ) {389 $order_ids[ $key ] = strval( $order_item['item_id'] );390 }391 }392 393 if ( count( $order_ids ) > 0 ) {394 $deletedProduct = $this->getDeletedProducts( $order_ids );395 foreach ( $deletedProduct as $id => $name ) {396 $key = array_search( $id, array_column( $new_orders, 'item_id' ) );397 if ( $key >= 0 ) {398 $new_orders[ $key ]['sku_id'] = $name;399 $new_orders[ $key ]['product_name'] = $name;400 $new_orders[ $key ]['product_category0'] = 'محصولات حذف شده';401 }402 }403 }404 405 $orders_for_sync = array_merge( $this->getErrorLogs(), $new_orders );406 407 return [ 'order' => $orders_for_sync, 'date' => $date ];408 }409 410 /**411 * Each time a data is not synchronized with the sokan, it is logged412 * @return void413 * @since 1.1.0414 */415 public function saveErrors( $errors ) {416 $logTable = $this->filters['log_table'];417 $this->db->query( " INSERT ignore INTO `$logTable`(`entity_id`,`error`,`payload`) VALUES " . implode( ',', $errors ) . ";" );418 }419 420 /**421 * get all error logs saved on db for sync again422 * @return array423 * @since 1.1.0424 */425 private function getErrorLogs(): array {426 $logTable = $this->filters['log_table'];427 $result = [];428 $res = $this->db->get_results( " SELECT * FROM `$logTable` ORDER BY `date`", ARRAY_A );429 430 if ( count( $res ) == 0 ) {431 return $result;432 }433 434 foreach ( $res as $log ) {435 if ( ! empty( $log['payload'] ) ) {436 array_push( $result, json_decode( $log['payload'], true ) );437 }438 }439 $this->db->query( "TRUNCATE TABLE $logTable" );440 441 return $result;442 }443 444 /**445 * get list of order ids for sync based on date and status filters446 * @return array447 * @since 1.2.0448 */449 private function getAvailableOrderIds(): array {450 451 $date = $this->filters['update_date'];452 $com_status = $this->filters['complete_status'];453 $ref_status = $this->filters['refunded_status'];454 $api_limitation = $this->filters['api_limitation'];455 456 $ids = $this->db->get_results(457 "SELECT `{$this->db->prefix}posts`.ID as id FROM `{$this->db->prefix}posts`230 ARRAY_A 231 ); 232 $result = []; 233 foreach ( $products as $product ) { 234 $result[ $product['order_item_id'] ] = $product['order_item_name']; 235 } 236 237 return $result; 238 } 239 240 /** 241 * return all order based on filters 242 * @return array invoices 243 * return list of invoices 244 * @since 1.1.0 245 */ 246 public function getAllOrders(): array { 247 $date = $this->filters['update_date']; 248 $ref_status = $this->filters['refunded_status']; 249 $customer_identity = $this->filters['customer_identity']; 250 251 if ( count( $ids = $this->getAvailableOrderIds() ) == 0 ) { 252 return [ 'order' => [], 'date' => $date ]; 253 } 254 255 $all_invoices = $this->getOrderData( $ids ); 256 $new_orders = []; 257 $product_ids = []; 258 259 foreach ( $all_invoices as $order_key => $value ) { 260 261 $date = $value['modified_date'] ?? $date; 262 $order_date = $value['post_date'] ?? $date; 263 $first_name = $value[ $this->order_attr['first_name'] ] ?? "مشتری"; 264 $last_name = $value[ $this->order_attr['last_name'] ] ?? "نامشخص"; 265 $customer_name = trim( trim( $first_name, " " ) . " " . trim( $last_name, " " ), " " ); 266 $customer_phone = $this->convertToEnNumbers( $value[ $this->order_attr['phone'] ] ?? "" ); 267 268 if ( preg_match( '/^(?:98|\+98|0098|0|\+980|00980)?9[0-9]{9}/', $customer_phone, $_phone, PREG_OFFSET_CAPTURE ) ) { 269 $_phone = $_phone[0][0]; 270 $_phone = str_replace( "+980", '+98', $_phone ); 271 $_phone = str_replace( "00980", '+98', $_phone ); 272 $customer_phone = preg_replace( '/^(?:98|\+98|0098|0)/', "0", $_phone ); 273 } 274 275 $customer_id = $value[ $this->order_attr['user_id'] ] ?? ( empty( $customer_phone ) ? $customer_name : $customer_phone ); 276 277 if ( $customer_identity == 'phone' and ! empty( $customer_phone ) ) { 278 $customer_id = trim( str_replace( "0", "", $customer_phone ), " " ); 279 } elseif ( $customer_identity == 'name' and $customer_name != "مشتری نامشخص" ) { 280 $customer_id = $customer_name; 281 } elseif ( $customer_id == 0 ) { 282 $customer_id = $customer_name != "مشتری نامشخص" ? $customer_name : $order_key; 283 } 284 285 $state = $value[ $this->order_attr['state'] ] ?? "نامشخص"; 286 $city = $value[ $this->order_attr['city'] ] ?? "نامشخص"; 287 288 if ( ! isset( $value['items'] ) and isset( $value['_order_total'] ) ) { 289 $value['items'][ $value['_order_total'] ]['_fee_amount'] = $value['_order_total']; 290 } elseif ( ! isset( $value['items'] ) ) { 291 continue; 292 } 293 294 foreach ( $value['items'] as $item_key => $item ) { 295 296 $qty = $item['_qty'] ?? 1; 297 $qty = abs( $qty ); 298 $discount = 0; 299 $unit_price = 0; 300 $total = 0; 301 $product_id = 'Undefined Product'; 302 $product_type = 'SERVICE'; 303 304 if ( isset( $item['_line_subtotal'] ) ) { 305 306 if ( $item['_line_subtotal'] > 0 ) { 307 $unit_price = $item['_line_subtotal'] / $qty; 308 } else { 309 $unit_price = $item['_line_total'] / $qty; 310 } 311 if ( $item['_line_total'] != 0 ) { 312 $total = $item['_line_total'] / $qty; 313 } 314 $discount = ( $unit_price - $total ) * $qty; 315 $product_type = 'PRODUCT'; 316 317 if ( ! empty( $item['_product_id'] ) ) { 318 $product_id = $item['_product_id']; 319 $product_ids[ $product_id ] = $product_id; 320 } 321 } else if ( isset( $item['cost'] ) ) { 322 323 $unit_price = (int) $item['cost']; 324 $product_id = 'هزینه ارسال'; 325 326 } else if ( isset( $item['_fee_amount'] ) ) { 327 $unit_price = (int) $item['_fee_amount']; 328 } 329 330 $weight = $item['pa_weight'] ?? 0; 331 332 $order = [ 333 'item_id' => (string) $item_key, 334 'invoice_id' => (string) $order_key, 335 'date' => (string) $order_date, 336 'unit_price' => abs( (int) $unit_price ), 337 'type' => "SALES", 338 'quantity' => (int) $qty, 339 'discount' => (int) $discount, 340 'weight' => (int) $weight, 341 'customer_id' => $customer_id, 342 'customer_name' => $customer_name, 343 'region0' => "ایران", 344 'region1' => $this->getRegionName( $state ), 345 'region2' => trim( $city, " " ), 346 'sku_id' => $product_id, 347 'product_name' => $product_id, 348 'product_type' => $product_type 349 ]; 350 351 if ( preg_match( '/^(?:98|\+98|0098|0)?9[0-9]{9}$/', $customer_phone ) ) { 352 $order['customer_phone_number'] = $customer_phone; 353 } 354 355 array_push( $new_orders, $order ); 356 357 if ( $value['status'] == $ref_status ) { 358 $refund_order = $order; 359 $refund_order['item_id'] = $refund_order['item_id'] . "_refunded"; 360 $refund_order['quantity'] = - $refund_order['quantity']; 361 $refund_order['discount'] = - $refund_order['discount']; 362 $refund_order['type'] = "RETURN"; 363 array_push( $new_orders, $refund_order ); 364 } 365 } 366 } 367 368 $all_products = $this->getProducts( $product_ids ); 369 $order_ids = []; 370 foreach ( $new_orders as $key => $order_item ) { 371 372 if ( isset( $all_products[ $order_item['sku_id'] ] ) ) { 373 374 $product = $all_products[ $order_item['sku_id'] ]; 375 $new_orders[ $key ]['product_name'] = $product['name']; 376 377 if ( isset( $product['brand'] ) ) { 378 $new_orders[ $key ]['product_brand0'] = $product['brand']; 379 } 380 if ( isset( $product['categories'] ) ) { 381 foreach ( $product['categories'] as $cat_key => $name ) { 382 $new_orders[ $key ][ 'product_category' . $cat_key ] = $name; 383 } 384 } 385 if ( $order_item['weight'] == 0 and isset( $product['weight'] ) ) { 386 $new_orders[ $key ]['weight'] = (int) $product['weight']; 387 } 388 } elseif ( $order_item['sku_id'] == 'Undefined Product' and $order_item['sku_id'] != 'هزینه ارسال' ) { 389 $order_ids[ $key ] = strval( $order_item['item_id'] ); 390 } 391 } 392 393 if ( count( $order_ids ) > 0 ) { 394 $deletedProduct = $this->getDeletedProducts( $order_ids ); 395 foreach ( $deletedProduct as $id => $name ) { 396 $key = array_search( $id, array_column( $new_orders, 'item_id' ) ); 397 if ( $key >= 0 ) { 398 $new_orders[ $key ]['sku_id'] = $name; 399 $new_orders[ $key ]['product_name'] = $name; 400 $new_orders[ $key ]['product_category0'] = 'محصولات حذف شده'; 401 } 402 } 403 } 404 405 $orders_for_sync = array_merge( $this->getErrorLogs(), $new_orders ); 406 407 return [ 'order' => $orders_for_sync, 'date' => $date ]; 408 } 409 410 /** 411 * Each time a data is not synchronized with the sokan, it is logged 412 * @return void 413 * @since 1.1.0 414 */ 415 public function saveErrors( $errors ) { 416 $logTable = $this->filters['log_table']; 417 $this->db->query( " INSERT ignore INTO `$logTable`(`entity_id`,`error`,`payload`) VALUES " . implode( ',', $errors ) . ";" ); 418 } 419 420 /** 421 * get all error logs saved on db for sync again 422 * @return array 423 * @since 1.1.0 424 */ 425 private function getErrorLogs(): array { 426 $logTable = $this->filters['log_table']; 427 $result = []; 428 $res = $this->db->get_results( " SELECT * FROM `$logTable` ORDER BY `date`", ARRAY_A ); 429 430 if ( count( $res ) == 0 ) { 431 return $result; 432 } 433 434 foreach ( $res as $log ) { 435 if ( ! empty( $log['payload'] ) ) { 436 array_push( $result, json_decode( $log['payload'], true ) ); 437 } 438 } 439 $this->db->query( "TRUNCATE TABLE $logTable" ); 440 441 return $result; 442 } 443 444 /** 445 * get list of order ids for sync based on date and status filters 446 * @return array 447 * @since 1.2.0 448 */ 449 private function getAvailableOrderIds(): array { 450 451 $date = $this->filters['update_date']; 452 $com_status = $this->filters['complete_status']; 453 $ref_status = $this->filters['refunded_status']; 454 $api_limitation = $this->filters['api_limitation']; 455 456 $ids = $this->db->get_results( 457 "SELECT `{$this->db->prefix}posts`.ID as id FROM `{$this->db->prefix}posts` 458 458 WHERE `{$this->db->prefix}posts`.post_status IN ('$com_status' , '$ref_status') 459 459 AND `{$this->db->prefix}posts`.post_modified > '$date' 460 460 GROUP BY `{$this->db->prefix}posts`.ID 461 461 ORDER BY `{$this->db->prefix}posts`.post_modified LIMIT $api_limitation ", 462 ARRAY_A463 );464 465 return apply_filters( "skng_get_all_order_ids_filter", array_column( $ids, 'id' ) );466 }467 468 /**469 * get order data of given id list470 *471 * @param $ids472 *473 * @return array474 * @since 1.2.0475 */476 private function getOrderData( $ids ): array {477 478 $attr_copy = $this->order_attr;479 array_push( $attr_copy, '_order_total' );480 $attr = implode( "','", $attr_copy );481 482 $all = $this->db->get_results( "462 ARRAY_A 463 ); 464 465 return apply_filters( "skng_get_all_order_ids_filter", array_column( $ids, 'id' ) ); 466 } 467 468 /** 469 * get order data of given id list 470 * 471 * @param $ids 472 * 473 * @return array 474 * @since 1.2.0 475 */ 476 private function getOrderData( $ids ): array { 477 478 $attr_copy = $this->order_attr; 479 array_push( $attr_copy, '_order_total' ); 480 $attr = implode( "','", $attr_copy ); 481 482 $all = $this->db->get_results( " 483 483 (SELECT `{$this->db->prefix}woocommerce_order_items`.order_item_id as item_id , 484 484 `{$this->db->prefix}woocommerce_order_items`.order_id as order_id, … … 513 513 ", ARRAY_A ); 514 514 515 $all_invoices = []; 516 foreach ( $all as $value ) { 517 518 if ( in_array( $value['meta_key'], $this->order_attr ) ) { 519 if ( ! ctype_space( $value['meta_value'] ) and ! empty( $value['meta_value'] ) ) { 520 $all_invoices[ $value['order_id'] ][ $value['meta_key'] ] = $value['meta_value']; 521 } 522 continue; 523 } 524 525 $all_invoices[ $value['order_id'] ]['modified_date'] = $value['modified_date']; 526 $all_invoices[ $value['order_id'] ]['post_date'] = $value['post_date']; 527 $all_invoices[ $value['order_id'] ]['status'] = $value['order_status']; 528 529 if ( $value['meta_key'] == '_order_total' ) { 530 $all_invoices[ $value['order_id'] ]['_order_total'] = $value['meta_value']; 531 continue; 532 } 533 534 $all_invoices[ $value['order_id'] ]['items'][ $value['item_id'] ][ $value['meta_key'] ] = $value['meta_value']; 535 536 } 537 538 return apply_filters( "skng_get_all_order_data_filter", $all_invoices ); 539 } 540 541 /** 542 * return persian name of given state key 543 * 544 * @param $state 545 * 546 * @return string 547 * @since 1.2.0 548 */ 549 private function getRegionName( $state ): string { 550 $symbols = array( 551 "استان", 552 "شهرستان", 553 "مقدس", 554 "شهر", 555 "روستا", 556 ",", 557 ".", 558 "،", 559 '!', 560 '"', 561 '#', 562 '$', 563 '%', 564 '&', 565 '(', 566 ')', 567 '*', 568 '+', 569 ',', 570 '-', 571 '.', 572 '/', 573 ':', 574 ';', 575 '<', 576 '>', 577 '=', 578 '?', 579 '@', 580 '[', 581 ']', 582 '^', 583 '_', 584 '{', 585 '}', 586 '|', 587 '~', 588 '`' 589 ); 590 $state = str_replace( $symbols, "", $state ); 591 592 if ( isset( $this->states[ $state ] ) ) { 593 return trim( $this->states[ $state ], " " ); 594 } 595 596 return trim( $state, " " ); 597 } 598 599 private function convertToEnNumbers( $string ) { 600 if ( empty( $string ) ) { 601 return ""; 602 } 603 $string = str_replace( ' ', '', $string ); 604 $persian = [ '۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹' ]; 605 $english = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]; 606 $string = str_replace( $persian, $english, $string ); 607 608 return filter_var( $string, FILTER_SANITIZE_NUMBER_INT ); 609 } 515 $all_invoices = []; 516 foreach ( $all as $value ) { 517 518 if ( in_array( $value['meta_key'], $this->order_attr ) ) { 519 if ( ! ctype_space( $value['meta_value'] ) and ! empty( $value['meta_value'] ) ) { 520 $all_invoices[ $value['order_id'] ][ $value['meta_key'] ] = $value['meta_value']; 521 } 522 continue; 523 } 524 525 $all_invoices[ $value['order_id'] ]['modified_date'] = $value['modified_date']; 526 $all_invoices[ $value['order_id'] ]['post_date'] = $value['post_date']; 527 $all_invoices[ $value['order_id'] ]['status'] = $value['order_status']; 528 529 if ( $value['meta_key'] == '_order_total' ) { 530 $all_invoices[ $value['order_id'] ]['_order_total'] = $value['meta_value']; 531 continue; 532 } 533 534 $all_invoices[ $value['order_id'] ]['items'][ $value['item_id'] ][ $value['meta_key'] ] = $value['meta_value']; 535 536 } 537 538 return apply_filters( "skng_get_all_order_data_filter", $all_invoices ); 539 } 540 541 /** 542 * return persian name of given state key 543 * 544 * @param $state 545 * 546 * @return string 547 * @since 1.2.0 548 */ 549 private function getRegionName( $state ): string { 550 $state = str_replace("استان", "", $state); 551 $state = str_replace("شهرستان", "", $state); 552 $state = str_replace("مقدس", "", $state); 553 $state = str_replace(",", "", $state); 554 $state = str_replace(".", "", $state); 555 $state = str_replace("،", "", $state); 556 557 if ( isset( $this->states[ $state ] ) ) { 558 return trim( $this->states[ $state ], " " ); 559 } 560 561 return trim( $state, " " ); 562 } 563 564 private function convertToEnNumbers( $string ) { 565 if ( empty( $string ) ) { 566 return ""; 567 } 568 $string = str_replace( ' ', '', $string ); 569 $persian = [ '۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹' ]; 570 $english = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]; 571 $string = str_replace( $persian, $english, $string ); 572 573 return filter_var( $string, FILTER_SANITIZE_NUMBER_INT ); 574 } 610 575 611 576 } -
sokan-integration/trunk/readme.txt
r2733673 r2735651 5 5 Tested up to: 5.9 6 6 Donate link: http://sokan.tech/ 7 Stable tag: 1.5. 17 Stable tag: 1.5.2 8 8 Requires PHP: 7.0 9 9 License: GPLv2 or later … … 79 79 == Changelog == 80 80 81 = 1.5.2 = 82 * بهبود عملکرد 83 84 81 85 = 1.5.1 = 82 86 * بهبود عملکرد … … 126 130 == Upgrade Notice == 127 131 132 = 1.5.2 = 133 * بهبود عملکرد 134 128 135 = 1.5.1 = 129 136 * بهبود عملکرد
Note: See TracChangeset
for help on using the changeset viewer.