Plugin Directory

Changeset 3185485


Ignore:
Timestamp:
11/11/2024 07:49:31 AM (14 months ago)
Author:
arture
Message:

Version 1.6.8

Location:
order-picking-app/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • order-picking-app/trunk/admin/partials/orderpickingapp-packing-page.php

    r3172741 r3185485  
    1818            <h2>BETA: DESKTOP PACKING</h2>
    1919            <style>
    20                 #packing {
     20                #orderpickingapp-packing {
    2121                    --bs-body-color: #000;
    2222                    color: #000 !important;
    2323                    --bs-white-rgb: rgb(0,0,0);
    2424                }
    25                 #packing p,
    26                 #packing li,
    27                 #packing span  { color: #000 !important; }
    28                 #packing .open { background-color: #24b3eb; }
    29                 #packing .packing_product.completed { background: #50d950; }
    30                 #packing .packing_product.backorder { background: #ff7100; }
    31                 #packing .packing_product .backorder {
     25                #orderpickingapp-packing p,
     26                #orderpickingapp-packing li,
     27                #orderpickingapp-packing span  { color: #000 !important; }
     28                #orderpickingapp-packing .open { background-color: #24b3eb; }
     29                #orderpickingapp-packing .packing_product.completed { background: #50d950; }
     30                #orderpickingapp-packing .packing_product.backorder { background: #ff7100; }
     31                #orderpickingapp-packing .packing_product .backorder {
    3232                    background: #ff7100;
    3333                    border-radius: 5px;
     
    3737                    padding: 5px;
    3838                }
    39                 #packing .clickers { font-size: 24px; }
    40                 #packing .decrement i { color: red; font-size: 24px; }
    41                 #packing .increment i { color: green; font-size: 24px; }
    42                 #packing .packedAmount { font-size: 30px; margin-bottom: 10px; }
     39                #orderpickingapp-packing .clickers { font-size: 24px; }
     40                #orderpickingapp-packing .decrement i { color: red; font-size: 24px; }
     41                #orderpickingapp-packing .increment i { color: green; font-size: 24px; }
     42                #orderpickingapp-packing .packedAmount { font-size: 30px; margin-bottom: 10px; }
    4343            </style>
    4444
     
    9494                            <?php foreach( $packing_order['products'] as $product ): ?>
    9595                                <tr class="packing_product" data-sku="<?php echo $product['sku']; ?>" data-barcode="<?php echo $product['barcode']; ?>" data-ordered="<?php echo $product['ordered']; ?>" data-unpacked="<?php echo $product['unpacked']; ?>">
    96                                     <td style="width: 33.3333%;">
     96                                    <td>
    9797                                        <div class="<?php echo $product['status']; ?>">
    9898                                            <p style="max-width: 50px;text-align: center;display: block; font-size: 9px; position: relative;margin: 0;">PICK</p>
    99                                             <i style="max-width: 50px;text-align: center;display: block; font-size: 9px;"><?php echo $product['quantity']; ?> / <?php echo $product['quantity'] - $product['backorder']; ?></i>
     99                                            <i style="max-width: 50px;text-align: center;display: block; font-size: 9px;"><?php echo $product['quantity']; ?> / <?php echo (int)$product['quantity'] - (int)$product['backorder']; ?></i>
    100100                                        </div>
    101101                                        <hr style="border-bottom: 1px solid #000; margin: 5px 0; max-width: 50px;">
    102102                                        <p style="max-width: 50px;text-align: center;display: block; font-size: 11px; margin-bottom: 0;">PACK</p>
    103                                         <i style="max-width: 50px;text-align: center;display: block;"><?php echo $product['ordered']; ?> / <span class="packed" style="font-size: 11px;"><?php echo $product['ordered'] - $product['unpacked']; ?></span></i>
     103                                        <i style="max-width: 50px;text-align: center;display: block;"><?php echo $product['ordered']; ?> / <span class="packed" style="font-size: 11px;"><?php echo (int)$product['ordered'] - (int)$product['unpacked']; ?></span></i>
    104104                                    </td>
    105                                     <td style="width: 33.3333%;">
     105                                    <td>
    106106                                        <img style="text-align: center; margin: 0 auto; max-width: 200px;" src="<?php echo $product['thumbnail']; ?>"/>
    107107                                    </td>
    108                                     <td style="width: 33.3333%;">
     108                                    <td>
    109109                                        <ul style="list-style: none; text-align: left; margin: 0; padding: 0;">
    110110                                            <li><strong><?php echo $product['title']; ?></strong></li>
     
    125125                                        </ul>
    126126                                    </td>
    127                                     <td>
     127                                    <td style="width: 220px;">
    128128                                        <div class="row" style="min-width: 150px;text-align: center;">
    129                                             <div class="col-4 clickers decrement" data-barcode="<?php echo ( isset($product['barcode']) && !empty($product['barcode']) )? $product['barcode'] : $product['sku']; ?>" data-ordered="<?php echo $product['ordered']; ?>"><span class="dashicons dashicons-remove"></span></div>
     129                                            <div class="col-4 clickers decrement" data-barcode="<?php echo ( isset($product['barcode']) && !empty($product['barcode']) )? $product['barcode'] : $product['sku']; ?>" data-ordered="<?php echo $product['ordered']; ?>">
     130                                                <span class="dashicons dashicons-remove" style="width: 30px; color: red !important;font-size: 30px;"></span>
     131                                            </div>
    130132                                            <span class="col-4 packedAmount">0</span>
    131                                             <div class="col-4 clickers increment" data-barcode="<?php echo ( isset($product['barcode']) && !empty($product['barcode']) )? $product['barcode'] : $product['sku']; ?>" data-ordered="<?php echo $product['ordered']; ?>"><span class="dashicons dashicons-insert"></span></div>
     133                                            <div class="col-4 clickers increment" data-barcode="<?php echo ( isset($product['barcode']) && !empty($product['barcode']) )? $product['barcode'] : $product['sku']; ?>" data-ordered="<?php echo $product['ordered']; ?>">
     134                                                <span class="dashicons dashicons-insert" style="width: 30px; color: green !important;font-size: 30px;"></span>
     135                                            </div>
    132136                                        </div>
    133137                                        <p style="cursor: pointer; text-align: center; text-decoration: underline; margin: 0 auto; display: block;" class="completeAmount" data-ordered="<?php echo $product['ordered']; ?>">Check all</p>
  • order-picking-app/trunk/includes/class-orderpickingapp.php

    r3172741 r3185485  
    88    private $productCategories;
    99
    10         public function __construct(){
    11             $this->load_dependencies();
    12             $this->define_admin_hooks();
    13 
    14             $this->orderedCategories = array();
    15             $this->productCategories = array();
    16 
    17             $path = wp_get_upload_dir()['basedir'];
    18             if (is_dir($path)) {
    19                 $pathComplete = $path;
    20                 $subpath = '/orderpickingapp/logs';
    21                 if (is_dir($pathComplete . $subpath)) {
    22                     $pathComplete .= $subpath;
     10    public function __construct(){
     11        $this->load_dependencies();
     12        $this->define_admin_hooks();
     13
     14        $this->orderedCategories = array();
     15        $this->productCategories = array();
     16
     17        $path = wp_get_upload_dir()['basedir'];
     18        if (is_dir($path)) {
     19            $pathComplete = $path;
     20            $subpath = '/orderpickingapp/logs';
     21            if (is_dir($pathComplete . $subpath)) {
     22                $pathComplete .= $subpath;
     23            } else {
     24                foreach (explode("/", $subpath) as $subpath_part) {
     25                    if (strlen($subpath_part) > 0) {
     26                        if (!is_dir($pathComplete . "/" . $subpath_part)) {
     27                            if (!mkdir($pathComplete . "/" . $subpath_part, 0777)) {
     28                                exit("Failed to create the subdirectory: " . $pathComplete . "/" . $subpath_part . "(" . error_get_last()['message'] . ")");
     29                            }
     30                        }
     31                        $pathComplete .= '/' . $subpath_part;
     32                    }
     33                }
     34            }
     35
     36            self::$logPath = $pathComplete;
     37            $logFilePath = $pathComplete . '/' . date('Y-m-d') . '.log';
     38            $logFileHandle = fopen($logFilePath, 'a');
     39            if ($logFileHandle === false) {
     40                exit("Failed to open the logfile for: " . $logFilePath . "(" . error_get_last()['message'] . ")");
     41            } else {
     42                self::$logFileHandle = $logFileHandle;
     43            }
     44        } else {
     45            exit("Failed to create logs in directory: " . $path);
     46        }
     47
     48        add_action('woocommerce_admin_order_item_headers', array($this, 'orderpickingapp_admin_order_item_headers'));
     49        add_action('woocommerce_admin_order_item_values', array($this, 'orderpickingapp_admin_order_item_values'), 10, 3);
     50
     51        add_filter('woocommerce_get_wp_query_args', function ($wp_query_args, $query_vars) {
     52            if (isset($query_vars['meta_query'])) {
     53                $meta_query = isset($wp_query_args['meta_query']) ? $wp_query_args['meta_query'] : [];
     54                $wp_query_args['meta_query'] = array_merge($meta_query, $query_vars['meta_query']);
     55            }
     56
     57            return $wp_query_args;
     58        }, 10, 2);
     59    }
     60
     61    public
     62    function orderpickingapp_admin_order_item_headers()
     63    {
     64        echo '<th>Picking</th>';
     65    }
     66
     67    public
     68    function orderpickingapp_admin_order_item_values($_product, $item, $item_id = null)
     69    {
     70        $picking_status = get_post_meta($item_id, 'picking_status', true);
     71        $backorder = get_post_meta($item_id, 'backorder', true);
     72
     73        $user_claimed = '-';
     74        if( method_exists($item, 'get_order_id') ){
     75            $user_claimed = get_post_meta($item->get_order_id(), 'user_claimed', true);
     76        }
     77
     78        if (isset($picking_status) && !empty($picking_status)) {
     79            echo '<td>Status: ' . $picking_status . '</br>Backorders: ' . $backorder . '</br>Picker: ' . ucfirst($user_claimed) . '</td>';
     80        } else {
     81            echo '<td></td>';
     82        }
     83
     84    }
     85
     86    private
     87    function load_dependencies()
     88    {
     89
     90        // Plugin defaults
     91        require_once plugin_dir_path(dirname(__FILE__)) . 'vendor/autoload.php';
     92        require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-orderpickingapp-admin.php';
     93        require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-orderpickingapp-loader.php';
     94        require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-feedback.php';
     95
     96        $this->loader = new OrderPickingApp_Loader();
     97    }
     98
     99    private
     100    function define_admin_hooks()
     101    {
     102
     103        // Default actions
     104        $admin = new OrderPickingApp_Admin();
     105        $this->loader->add_action('admin_enqueue_scripts', $admin, 'enqueue_plugin_styles_scripts');
     106        $this->loader->add_action('admin_menu', $admin, 'add_orderpickingapp_admin_pages');
     107        $this->loader->add_action('admin_init', $admin, 'display_orderpickingapp_panel_fields');
     108        $this->loader->add_action('admin_notices', $admin, 'missing_app_token_message');
     109        $this->loader->add_action('wp_ajax_save_app_settings', $admin, 'save_app_settings');
     110        $this->loader->add_action('wp_ajax_reset_api_key', $admin, 'reset_api_key');
     111        $this->loader->add_action('wp_ajax_create_user_account', $admin, 'create_user_account');
     112        $this->loader->add_action('init', $admin, 'add_pickingroute_taxonomy');
     113
     114        $this->loader->add_action('plugins_loaded', $this, 'mc_load_textdomain');
     115        $this->loader->add_action('rest_api_init', $this, 'wp_register_endpoints');
     116
     117        $uninstall_feedback = new OPA_Uninstall_Feedback();
     118    }
     119
     120    public
     121    function run()
     122    {
     123        $this->loader->run();
     124    }
     125
     126    public
     127    function mc_load_textdomain()
     128    {
     129        $plugin_rel_path = basename(dirname(__FILE__)) . '/languages';
     130        load_plugin_textdomain('orderpickingapp', false, $plugin_rel_path);
     131    }
     132
     133    public
     134    function wp_register_endpoints()
     135    {
     136
     137        register_rest_route('picking/v1', '/get-settings', array(
     138            'methods' => 'GET',
     139            'callback' => array($this, 'getSettings'),
     140            'permission_callback' => '__return_true',
     141        ));
     142
     143        register_rest_route('picking/v1', '/get-order-products', array(
     144            'methods' => 'GET',
     145            'callback' => array($this, 'getOrderProducts'),
     146            'permission_callback' => '__return_true',
     147        ));
     148
     149        register_rest_route('picking/v1', '/pickinglist', array(
     150            'methods' => 'GET',
     151            'callback' => array($this, 'getPickingList'),
     152            'permission_callback' => '__return_true',
     153        ));
     154
     155        register_rest_route('picking/v1', '/update-order-products', array(
     156            'methods' => 'POST',
     157            'callback' => array($this, 'updateOrderProducts'),
     158            'permission_callback' => '__return_true',
     159        ));
     160
     161        register_rest_route('picking/v1', '/reset-order-products', array(
     162            'methods' => 'GET',
     163            'callback' => array($this, 'resetOrderProducts'),
     164            'permission_callback' => '__return_true',
     165        ));
     166
     167        register_rest_route('picking/v1', '/get-packing-orders', array(
     168            'methods' => 'GET',
     169            'callback' => array($this, 'requestPackingOrders'),
     170            'permission_callback' => '__return_true',
     171        ));
     172
     173        register_rest_route('picking/v1', '/update-order-status', array(
     174            'methods' => 'POST',
     175            'callback' => array($this, 'updateOrderStatus'),
     176            'permission_callback' => '__return_true',
     177        ));
     178
     179        register_rest_route('picking/v1', '/create-order-note', array(
     180            'methods' => 'POST',
     181            'callback' => array($this, 'createOrderNote'),
     182            'permission_callback' => '__return_true',
     183        ));
     184
     185        register_rest_route('picking/v1', '/get-categories', array(
     186            'methods' => 'GET',
     187            'callback' => array($this, 'getCategories'),
     188            'permission_callback' => '__return_true',
     189        ));
     190
     191        register_rest_route('picking/v1', '/get-product', array(
     192            'methods' => 'GET',
     193            'callback' => array($this, 'getProduct'),
     194            'permission_callback' => '__return_true',
     195        ));
     196        register_rest_route('picking/v1', '/update-product', array(
     197            'methods' => 'POST',
     198            'callback' => array($this, 'updateProduct'),
     199            'permission_callback' => '__return_true',
     200        ));
     201
     202        register_rest_route('picking/v1', '/reset-picking-orders', array(
     203            'methods' => 'GET',
     204            'callback' => array($this, 'resetPickingOrders'),
     205            'permission_callback' => '__return_true',
     206        ));
     207
     208        register_rest_route('picking/v1', '/get-customers', array(
     209            'methods' => 'GET',
     210            'callback' => array($this, 'getCustomers'),
     211            'permission_callback' => '__return_true',
     212        ));
     213        register_rest_route('picking/v1', '/create-order', array(
     214            'methods' => 'POST',
     215            'callback' => array($this, 'createOrder'),
     216            'permission_callback' => '__return_true',
     217        ));
     218    }
     219
     220    public
     221    function getSettings($request)
     222    {
     223
     224        header('Access-Control-Allow-Origin: *');
     225        header("Access-Control-Allow-Methods: GET");
     226
     227        $Products = array();
     228        if (class_exists('WooCommerce')) {
     229
     230            $token = $request->get_param('token');
     231
     232            if (isset($token)) {
     233
     234                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     235                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     236
     237                    $post_status = array('wc-processing');
     238                    $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
     239                    if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
     240                        $post_status = (array)$orderpickingapp_order_status;
     241                    }
     242
     243                    $order_statussen = array();
     244                    foreach ($post_status as $status) {
     245                        $order_statussen[] = str_replace('wc-', '', $status);
     246                    }
     247
     248                    $args = array(
     249                        'status' => $order_statussen,
     250                        'limit' => -1,
     251                        'meta_query' => array(
     252                            'relation' => 'OR',
     253                            array(
     254                                'relation' => 'AND',
     255                                array(
     256                                    'key' => 'picking_status',
     257                                    'value' => 'packing',
     258                                    'compare' => '!=',
     259                                ),
     260                                array(
     261                                    'key' => 'picking_status',
     262                                    'value' => 'completed',
     263                                    'compare' => '!=',
     264                                ),
     265                            ),
     266                            array(
     267                                'key' => 'picking_status',
     268                                'compare' => 'NOT EXISTS',
     269                            )
     270                        ),
     271                        'order' => 'ASC',
     272                    );
     273
     274                    $pickingDate = get_option('pickingDate');
     275                    if (isset($pickingDate) && !empty($pickingDate)) {
     276                        $args['date_query'] = array(
     277                            array(
     278                                'after' => $pickingDate,
     279                            ),
     280                        );
     281                    }
     282
     283                    $query = new WC_Order_Query($args);
     284                    $picking_orders = $query->get_orders();
     285
     286                    $total_picking_orders = count($picking_orders);
     287
     288                    $user_orders = array();
     289                    foreach ($picking_orders as $picking_order) {
     290                        $user_claimed = get_post_meta($picking_order->get_id(), 'user_claimed', true);
     291
     292                        if (isset($user_claimed) && !empty($user_claimed) ) {
     293                            if (isset($user_orders[$user_claimed])) {
     294                                $user_orders[$user_claimed] = $user_orders[$user_claimed] + 1;
     295                            } else {
     296                                $user_orders[$user_claimed] = 1;
     297                            }
     298                        }
     299
     300                    }
     301
     302                    $args = array(
     303                        'status' => $order_statussen,
     304                        'limit' => -1,
     305                        'meta_query' => array(
     306                            array(
     307                                'key' => 'picking_status',
     308                                'value' => 'packing',
     309                                'compare' => '=',
     310                            )
     311                        ),
     312
     313                    );
     314                    $query = new WC_Order_Query($args);
     315                    $packing_orders = $query->get_orders();
     316                    $total_packing_orders = count($packing_orders);
     317                    $total_backorders = 0;
     318
     319                    if (count($packing_orders) > 0) {
     320                        foreach ($packing_orders as $packing_order) {
     321                            foreach ($packing_order->get_items() as $item_id => $item) {
     322                                $backorder = get_post_meta($item_id, 'backorder', true);
     323
     324                                if ($backorder !== '0' && !empty($backorder)) {
     325                                    $total_backorders++;
     326                                    break;
     327                                }
     328
     329                            }
     330                        }
     331                    }
     332
     333                    $output = array(
     334                        'total_picking_orders' => (int)$total_picking_orders,
     335                        'total_packing_orders' => (int)$total_packing_orders,
     336                        'total_backorders' => (int)$total_backorders,
     337                        'user_orders' => $user_orders
     338                    );
     339                    wp_send_json($output);
    23340                } else {
    24                     foreach (explode("/", $subpath) as $subpath_part) {
    25                         if (strlen($subpath_part) > 0) {
    26                             if (!is_dir($pathComplete . "/" . $subpath_part)) {
    27                                 if (!mkdir($pathComplete . "/" . $subpath_part, 0777)) {
    28                                     exit("Failed to create the subdirectory: " . $pathComplete . "/" . $subpath_part . "(" . error_get_last()['message'] . ")");
    29                                 }
    30                             }
    31                             $pathComplete .= '/' . $subpath_part;
    32                         }
    33                     }
    34                 }
    35 
    36                 self::$logPath = $pathComplete;
    37                 $logFilePath = $pathComplete . '/' . date('Y-m-d') . '.log';
    38                 $logFileHandle = fopen($logFilePath, 'a');
    39                 if ($logFileHandle === false) {
    40                     exit("Failed to open the logfile for: " . $logFilePath . "(" . error_get_last()['message'] . ")");
    41                 } else {
    42                     self::$logFileHandle = $logFileHandle;
     341                    header("HTTP/1.1 401 Unauthorized");
     342                    exit;
    43343                }
    44344            } else {
    45                 exit("Failed to create logs in directory: " . $path);
     345                header("HTTP/1.1 401 Unauthorized");
     346                exit;
    46347            }
    47 
    48             add_action('woocommerce_admin_order_item_headers', array($this, 'orderpickingapp_admin_order_item_headers'));
    49             add_action('woocommerce_admin_order_item_values', array($this, 'orderpickingapp_admin_order_item_values'), 10, 3);
    50 
    51             add_filter('woocommerce_get_wp_query_args', function ($wp_query_args, $query_vars) {
    52                 if (isset($query_vars['meta_query'])) {
    53                     $meta_query = isset($wp_query_args['meta_query']) ? $wp_query_args['meta_query'] : [];
    54                     $wp_query_args['meta_query'] = array_merge($meta_query, $query_vars['meta_query']);
     348        }
     349    }
     350
     351    public
     352    function updateOrderProducts($request)
     353    {
     354
     355        header('Access-Control-Allow-Origin: *');
     356        header("Access-Control-Allow-Credentials: true");
     357        header('Access-Control-Allow-Methods: POST');
     358        header('Access-Control-Max-Age: 1000');
     359        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');
     360
     361        $body = $request->get_body();
     362        $data = json_decode($body, true);
     363
     364        if (isset($data[0]['orderid'])) {
     365            $data = $data[0];
     366        }
     367
     368        if (class_exists('WooCommerce')) {
     369            $token = $request->get_param('token');
     370            if (isset($token)) {
     371                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     372                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     373
     374                    $currency_symbol = get_woocommerce_currency_symbol();
     375                    $currency_symbol = html_entity_decode($currency_symbol);
     376
     377                    if (isset($data['products']) && !empty($data['products'])) {
     378
     379                        $products = json_decode($data['products'], true);
     380
     381                        // Iterate picked products
     382                        $order_notes_done = array();
     383                        foreach ($products as $product) {
     384
     385                            $picked_amount = $product['ordered'] - $product['backorder'];
     386
     387                            // Iterate related orders for this product
     388                            foreach ($product['orders'] as $order) {
     389                                $Order = new WC_Order($order['orderid']);
     390
     391                                if (!in_array($order['orderid'], $order_notes_done)) {
     392                                    $Order->add_order_note('Order Picking App | Order picking completed by ' . $data['appuser'] . '. Order now available for packing.');
     393                                    $Order->update_meta_data('picking_status', $data['status']);
     394                                    $this->log('Order picking completed for order:  ' . $order['orderid'] . ' by ' . $data['appuser'], 'Info');
     395                                    $Order->save();
     396
     397                                    $order_notes_done[$order['orderid']] = $order['orderid'];
     398                                }
     399
     400                                // Check for existing product inside order
     401                                foreach ($Order->get_items() as $item_id => $item) {
     402                                    $product_processed_stock = $item->get_quantity();
     403
     404                                    // Set order item/product status to picked
     405                                    $variation_id = $item->get_variation_id();
     406                                    if (isset($variation_id) && !empty($variation_id)) {
     407                                        $product_id = $variation_id;
     408                                    } else {
     409                                        $product_id = $item->get_product_id();
     410                                    }
     411
     412                                    if (isset($product_id) && $product_id == $product['product_id']) {
     413                                        if ($product['backorder'] == 0) {
     414                                            update_post_meta($item_id, 'picking_status', 'completed');
     415                                            update_post_meta($item_id, 'backorder', '0');
     416                                        } elseif ($picked_amount >= $product_processed_stock) {
     417                                            $picked_amount = $picked_amount - $product_processed_stock;
     418                                            update_post_meta($item_id, 'picking_status', 'completed');
     419                                            update_post_meta($item_id, 'backorder', '0');
     420                                        } else {
     421                                            update_post_meta($item_id, 'picking_status', 'backorder');
     422                                            update_post_meta($item_id, 'backorder', $product['backorder']);
     423                                        }
     424                                        break;
     425                                    } elseif ((!isset($product_id) || empty($product_id)) && $item_id == $product['product_id']) {
     426                                        if ($product['backorder'] == 0) {
     427                                            update_post_meta($item_id, 'picking_status', 'completed');
     428                                            update_post_meta($item_id, 'backorder', '0');
     429                                        } elseif ($picked_amount >= $product_processed_stock) {
     430                                            $picked_amount = $picked_amount - $product_processed_stock;
     431                                            update_post_meta($item_id, 'picking_status', 'completed');
     432                                            update_post_meta($item_id, 'backorder', '0');
     433                                        } else {
     434                                            update_post_meta($item_id, 'picking_status', 'backorder');
     435                                            update_post_meta($item_id, 'backorder', $product['backorder']);
     436                                        }
     437                                        break;
     438                                    }
     439                                }
     440                            }
     441                        }
     442                    }
     443
     444                    $post_status = array('wc-processing');
     445                    $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
     446                    if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
     447                        $post_status = (array)$orderpickingapp_order_status;
     448                    }
     449
     450                    $order_statussen = array();
     451                    foreach ($post_status as $status) {
     452                        $order_statussen[] = str_replace('wc-', '', $status);
     453                    }
     454
     455                    $args = array(
     456                        'status' => $order_statussen,
     457                        'limit' => -1,
     458                        'meta_query' => array(
     459                            'relation' => 'OR',
     460                            array(
     461                                'relation' => 'AND',
     462                                array(
     463                                    'key' => 'picking_status',
     464                                    'value' => 'packing',
     465                                    'compare' => '!=',
     466                                ),
     467                                array(
     468                                    'key' => 'picking_status',
     469                                    'value' => 'completed',
     470                                    'compare' => '!=',
     471                                ),
     472                            ),
     473                            array(
     474                                'key' => 'picking_status',
     475                                'compare' => 'NOT EXISTS',
     476                            )
     477                        ),
     478                        'order' => 'ASC',
     479                    );
     480
     481                    $pickingDate = get_option('pickingDate');
     482                    if (isset($pickingDate) && !empty($pickingDate)) {
     483                        $args['date_query'] = array(
     484                            array(
     485                                'after' => $pickingDate,
     486                            ),
     487                        );
     488                    }
     489
     490                    $query = new WC_Order_Query($args);
     491                    $shop_orders = $query->get_orders();
     492                    $total_picking_orders = count($shop_orders);
     493
     494                    $open_picking_orders = array();
     495                    foreach ($shop_orders as $total_picking_order) {
     496                        $total_picking_order_id = $total_picking_order->get_id();
     497
     498                        $total_items = 0;
     499                        foreach ($total_picking_order->get_items() as $item_id => $item) {
     500                            $product_id = $item->get_product_id();
     501                            if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php') && !empty($product_id)) {
     502                                $product_info = wc_get_product($product_id);
     503                                $product_type = $product_info->get_type();
     504                                if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     505                                    $total_items = $total_items + $item->get_quantity();
     506                                }
     507                            } else {
     508                                $total_items = $total_items + $item->get_quantity();
     509                            }
     510                        }
     511
     512                        $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
     513                        if (empty($lastname)) {
     514                            $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
     515                        }
     516
     517                        $order_number = $total_picking_order_id;
     518                        $order_prefix = get_option('order_prefix');
     519                        if( isset($order_prefix) && !empty($order_prefix) ){
     520                            $order_number = $order_prefix . $total_picking_order_id;
     521                        }
     522
     523                        $open_picking_orders[] = array(
     524                            'orderid' => $total_picking_order_id,
     525                            'order_number' => $order_number,
     526                            'date' => substr($total_picking_order->get_date_created(), 5, 5),
     527                            'items' => $total_items,
     528                            'total' => $currency_symbol . ' ' . $total_picking_order->get_total(),
     529                            'lastname' => $lastname,
     530                            'claimed_by' => get_post_meta($total_picking_order_id, 'user_claimed', true),
     531                        );
     532                    }
     533
     534                    $args = array(
     535                        'status' => $order_statussen,
     536                        'limit' => -1,
     537                        'meta_query' => array(
     538                            array(
     539                                'key' => 'picking_status',
     540                                'value' => 'packing',
     541                                'compare' => '=',
     542                            )
     543                        )
     544                    );
     545                    $query = new WC_Order_Query($args);
     546                    $packing_orders = $query->get_orders();
     547                    $total_packing_orders = count($packing_orders);
     548                    $total_backorders = 0;
     549
     550                    if (count($packing_orders) > 0) {
     551                        foreach ($packing_orders as $packing_order) {
     552                            foreach ($packing_order->get_items() as $item_id => $item) {
     553                                $backorder = get_post_meta($item_id, 'backorder', true);
     554
     555                                if ($backorder !== '0' && !empty($backorder)) {
     556                                    $total_backorders++;
     557                                    break;
     558                                }
     559
     560                            }
     561                        }
     562                    }
     563
     564                    $output = array(
     565                        'total_picking_orders' => (int)$total_picking_orders,
     566                        'total_packing_orders' => (int)$total_packing_orders,
     567                        'total_backorders' => (int)$total_backorders,
     568                        'open_picking_orders' => $open_picking_orders
     569                    );
     570                    wp_send_json($output);
     571                } else {
     572                    header("HTTP/1.1 401 Unauthorized");
     573                    exit;
    55574                }
    56 
    57                 return $wp_query_args;
    58             }, 10, 2);
    59         }
    60 
    61         public
    62         function orderpickingapp_admin_order_item_headers()
    63         {
    64             echo '<th>Picking</th>';
    65         }
    66 
    67         public
    68         function orderpickingapp_admin_order_item_values($_product, $item, $item_id = null)
    69         {
    70             $picking_status = get_post_meta($item_id, 'picking_status', true);
    71             $backorder = get_post_meta($item_id, 'backorder', true);
    72 
    73             try {
    74                 $user_claimed = get_post_meta($item->get_order_id(), 'user_claimed', true);
    75             } catch (myCustomException $e) {
    76                 $user_claimed = '-';
     575            } else {
     576                header("HTTP/1.1 401 Unauthorized");
     577                exit;
    77578            }
    78 
    79             if (isset($picking_status) && !empty($picking_status)) {
    80                 echo '<td>Status: ' . $picking_status . '</br>Backorders: ' . $backorder . '</br>Picker: ' . ucfirst($user_claimed) . '</td>';
     579        }
     580        exit;
     581    }
     582
     583    public
     584    function resetPickingOrders($request)
     585    {
     586
     587        header('Access-Control-Allow-Origin: *');
     588        header("Access-Control-Allow-Methods: GET");
     589
     590        if (class_exists('WooCommerce')) {
     591            $token = $request->get_param('token');
     592            $appuser = $request->get_param('appuser');
     593
     594
     595            if (isset($token)) {
     596                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     597                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     598
     599                    $post_status = array('wc-processing');
     600                    $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
     601                    if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
     602                        $post_status = (array)$orderpickingapp_order_status;
     603                    }
     604
     605                    $order_statussen = array();
     606                    foreach ($post_status as $status) {
     607                        $order_statussen[] = str_replace('wc-', '', $status);
     608                    }
     609
     610                    $args = array(
     611                        'status' => $order_statussen,
     612                        'limit' => -1,
     613                        'meta_query' => array(
     614                            'relation' => 'OR',
     615                            array(
     616                                'relation' => 'AND',
     617                                array(
     618                                    'key' => 'picking_status',
     619                                    'value' => 'packing',
     620                                    'compare' => '!=',
     621                                ),
     622                                array(
     623                                    'key' => 'picking_status',
     624                                    'value' => 'completed',
     625                                    'compare' => '!=',
     626                                ),
     627                            ),
     628                            array(
     629                                'key' => 'picking_status',
     630                                'compare' => 'NOT EXISTS',
     631                            )
     632                        ),
     633                        'order' => 'ASC',
     634                    );
     635
     636                    $pickingDate = get_option('pickingDate');
     637                    if (isset($pickingDate) && !empty($pickingDate)) {
     638                        $args['date_query'] = array(
     639                            array(
     640                                'after' => $pickingDate,
     641                            ),
     642                        );
     643                    }
     644
     645                    $query = new WC_Order_Query($args);
     646                    $picking_orders = $query->get_orders();
     647
     648                    foreach ($picking_orders as $picking_order) {
     649                        $picking_order_id = $picking_order->get_id();
     650
     651                        if (!empty($appuser)) {
     652                            $user_claimed = get_post_meta($picking_order_id, 'user_claimed', true);
     653                            if (isset($user_claimed) && !empty($user_claimed) && $user_claimed != $appuser) {
     654                                continue;
     655                            }
     656                        }
     657
     658                        delete_post_meta($picking_order_id, 'picking_status');
     659                        delete_post_meta($picking_order_id, 'user_claimed');
     660                        delete_post_meta($picking_order_id, 'batch_id');
     661                    }
     662
     663                } else {
     664                    header("HTTP/1.1 401 Unauthorized");
     665                    exit;
     666                }
    81667            } else {
    82                 echo '<td></td>';
     668                header("HTTP/1.1 401 Unauthorized");
     669                exit;
    83670            }
    84 
    85         }
    86 
    87         private
    88         function load_dependencies()
    89         {
    90 
    91             // Plugin defaults
    92             require_once plugin_dir_path(dirname(__FILE__)) . 'vendor/autoload.php';
    93             require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-orderpickingapp-admin.php';
    94             require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-orderpickingapp-loader.php';
    95             require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-feedback.php';
    96 
    97             $this->loader = new OrderPickingApp_Loader();
    98         }
    99 
    100         private
    101         function define_admin_hooks()
    102         {
    103 
    104             // Default actions
    105             $admin = new OrderPickingApp_Admin();
    106             $this->loader->add_action('admin_enqueue_scripts', $admin, 'enqueue_plugin_styles_scripts');
    107             $this->loader->add_action('admin_menu', $admin, 'add_orderpickingapp_admin_pages');
    108             $this->loader->add_action('admin_init', $admin, 'display_orderpickingapp_panel_fields');
    109             $this->loader->add_action('admin_notices', $admin, 'missing_app_token_message');
    110             $this->loader->add_action('wp_ajax_save_app_settings', $admin, 'save_app_settings');
    111             $this->loader->add_action('wp_ajax_reset_api_key', $admin, 'reset_api_key');
    112             $this->loader->add_action('wp_ajax_create_user_account', $admin, 'create_user_account');
    113             $this->loader->add_action('init', $admin, 'add_pickingroute_taxonomy');
    114 
    115             $this->loader->add_action('plugins_loaded', $this, 'mc_load_textdomain');
    116             $this->loader->add_action('rest_api_init', $this, 'wp_register_endpoints');
    117 
    118             $uninstall_feedback = new OPA_Uninstall_Feedback();
    119         }
    120 
    121         public
    122         function run()
    123         {
    124             $this->loader->run();
    125         }
    126 
    127         public
    128         function mc_load_textdomain()
    129         {
    130             $plugin_rel_path = basename(dirname(__FILE__)) . '/languages';
    131             load_plugin_textdomain('orderpickingapp', false, $plugin_rel_path);
    132         }
    133 
    134         public
    135         function wp_register_endpoints()
    136         {
    137 
    138             register_rest_route('picking/v1', '/get-settings', array(
    139                 'methods' => 'GET',
    140                 'callback' => array($this, 'getSettings'),
    141                 'permission_callback' => '__return_true',
     671        }
     672        exit;
     673    }
     674
     675    public
     676    function resetOrderProducts($request)
     677    {
     678
     679        header('Access-Control-Allow-Origin: *');
     680        header("Access-Control-Allow-Methods: GET");
     681
     682        if (class_exists('WooCommerce')) {
     683            $token = $request->get_param('token');
     684            $orderid = $request->get_param('orderid');
     685            $appuser = $request->get_param('appuser');
     686            if (isset($token)) {
     687                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     688                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     689
     690                    $currency_symbol = get_woocommerce_currency_symbol();
     691                    $currency_symbol = html_entity_decode($currency_symbol);
     692
     693                    $Order = new WC_Order($orderid);
     694
     695                    $Order->add_order_note('Order Picking App | Order picking reset by ' . $appuser . '. Order reset to picking list.');
     696                    delete_post_meta($orderid, 'picking_status');
     697                    $this->log('Order picking reset for order:  ' . $orderid . ' by ' . $appuser, 'Info');
     698
     699                    foreach ($Order->get_items() as $item_id => $item) {
     700                        delete_post_meta($item_id, 'picking_status');
     701                        delete_post_meta($item_id, 'backorder');
     702                    }
     703
     704                    $post_status = array('wc-processing');
     705                    $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
     706                    if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
     707                        $post_status = (array)$orderpickingapp_order_status;
     708                    }
     709
     710                    $order_statussen = array();
     711                    foreach ($post_status as $status) {
     712                        $order_statussen[] = str_replace('wc-', '', $status);
     713                    }
     714
     715                    $args = array(
     716                        'status' => $order_statussen,
     717                        'limit' => -1,
     718                        'meta_query' => array(
     719                            'relation' => 'OR',
     720                            array(
     721                                'relation' => 'AND',
     722                                array(
     723                                    'key' => 'picking_status',
     724                                    'value' => 'packing',
     725                                    'compare' => '!=',
     726                                ),
     727                                array(
     728                                    'key' => 'picking_status',
     729                                    'value' => 'completed',
     730                                    'compare' => '!=',
     731                                ),
     732                            ),
     733                            array(
     734                                'key' => 'picking_status',
     735                                'compare' => 'NOT EXISTS',
     736                            )
     737                        ),
     738                        'order' => 'ASC',
     739                    );
     740
     741                    $pickingDate = get_option('pickingDate');
     742                    if (isset($pickingDate) && !empty($pickingDate)) {
     743                        $args['date_query'] = array(
     744                            array(
     745                                'after' => $pickingDate,
     746                            ),
     747                        );
     748                    }
     749
     750                    $query = new WC_Order_Query($args);
     751                    $shop_orders = $query->get_orders();
     752                    $total_picking_orders = count($shop_orders);
     753
     754                    $open_picking_orders = array();
     755                    foreach ($shop_orders as $total_picking_order) {
     756                        $total_picking_order_id = $total_picking_order->get_id();
     757
     758                        $total_items = 0;
     759                        foreach ($total_picking_order->get_items() as $item_id => $item) {
     760                            if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
     761                                $product_id = $item->get_product_id();
     762                                $product_info = wc_get_product($product_id);
     763                                $product_type = $product_info->get_type();
     764                                if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     765                                    $total_items = $total_items + $item->get_quantity();
     766                                }
     767                            } else {
     768                                $total_items = $total_items + $item->get_quantity();
     769                            }
     770                        }
     771
     772                        $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
     773                        if (empty($lastname)) {
     774                            $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
     775                        }
     776
     777                        $order_number = $total_picking_order_id;
     778                        $order_prefix = get_option('order_prefix');
     779                        if( isset($order_prefix) && !empty($order_prefix) ){
     780                            $order_number = $order_prefix . $total_picking_order_id;
     781                        }
     782
     783                        $open_picking_orders[] = array(
     784                            'orderid' => $total_picking_order_id,
     785                            'order_number' => $order_number,
     786                            'date' => substr($total_picking_order->get_date_created(), 5, 5),
     787                            'items' => $total_items,
     788                            'total' => $currency_symbol . ' ' . $total_picking_order->get_total(),
     789                            'lastname' => $lastname,
     790                            'claimed_by' => get_post_meta($total_picking_order_id, 'user_claimed', true),
     791                        );
     792                    }
     793
     794                    $args = array(
     795                        'status' => $order_statussen,
     796                        'limit' => -1,
     797                        'meta_query' => array(
     798                            array(
     799                                'key' => 'picking_status',
     800                                'value' => 'packing',
     801                                'compare' => '=',
     802                            )
     803                        )
     804                    );
     805                    $query = new WC_Order_Query($args);
     806                    $packing_orders = $query->get_orders();
     807                    $total_packing_orders = count($packing_orders);
     808                    $total_backorders = 0;
     809
     810                    if (count($packing_orders) > 0) {
     811                        foreach ($packing_orders as $packing_order) {
     812                            foreach ($packing_order->get_items() as $item_id => $item) {
     813                                $backorder = get_post_meta($item_id, 'backorder', true);
     814
     815                                if ($backorder !== '0' && !empty($backorder)) {
     816                                    $total_backorders++;
     817                                    break;
     818                                }
     819
     820                            }
     821                        }
     822                    }
     823
     824                    $output = array(
     825                        'total_picking_orders' => (int)$total_picking_orders,
     826                        'total_packing_orders' => (int)$total_packing_orders,
     827                        'total_backorders' => (int)$total_backorders,
     828                        'open_picking_orders' => $open_picking_orders
     829                    );
     830                    wp_send_json($output);
     831                } else {
     832                    header("HTTP/1.1 401 Unauthorized");
     833                    exit;
     834                }
     835            } else {
     836                header("HTTP/1.1 401 Unauthorized");
     837                exit;
     838            }
     839        }
     840        exit;
     841    }
     842
     843    public
     844    function updateOrderStatus($request)
     845    {
     846
     847        header('Access-Control-Allow-Origin: *');
     848        header("Access-Control-Allow-Credentials: true");
     849        header('Access-Control-Allow-Methods: POST');
     850        header('Access-Control-Max-Age: 1000');
     851        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');
     852
     853        $body = $request->get_body();
     854        $data = json_decode($body, true);
     855
     856        if (isset($data[0]['orderid'])) {
     857            $data = $data[0];
     858        }
     859
     860        if (class_exists('WooCommerce')) {
     861
     862            $token = $request->get_param('token');
     863            if (isset($token)) {
     864
     865                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     866                $auto_completed_order = get_option('auto_completed_order');
     867                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     868
     869                    $currency_symbol = get_woocommerce_currency_symbol();
     870                    $currency_symbol = html_entity_decode($currency_symbol);
     871
     872                    if (isset($data['orderid']) && !empty($data['orderid'])) {
     873                        $Order = new WC_Order($data['orderid']);
     874                        if (!empty($Order)) {
     875
     876                            $Order->add_order_note('Order Picking App | Order packing completed by ' . $data['appuser']);
     877                            $Order->update_meta_data('picking_status', $data['status']);
     878
     879                            if (isset($data['status']) && $data['status'] == 'completed' && isset($auto_completed_order) && $auto_completed_order == 'yes') {
     880                                $Order->update_status('completed');
     881                            }
     882
     883                            $this->log('Order packing completed for order:  ' . $data['orderid'] . ' by ' . $data['appuser'], 'Info');
     884                            $Order->save();
     885
     886                            $post_status = array('wc-processing');
     887                            $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
     888                            if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
     889                                $post_status = (array)$orderpickingapp_order_status;
     890                            }
     891
     892                            $order_statussen = array();
     893                            foreach ($post_status as $status) {
     894                                $order_statussen[] = str_replace('wc-', '', $status);
     895                            }
     896
     897                            $args = array(
     898                                'status' => $order_statussen,
     899                                'limit' => -1,
     900                                'meta_query' => array(
     901                                    'relation' => 'OR',
     902                                    array(
     903                                        'relation' => 'AND',
     904                                        array(
     905                                            'key' => 'picking_status',
     906                                            'value' => 'packing',
     907                                            'compare' => '!=',
     908                                        ),
     909                                        array(
     910                                            'key' => 'picking_status',
     911                                            'value' => 'completed',
     912                                            'compare' => '!=',
     913                                        ),
     914                                    ),
     915                                    array(
     916                                        'key' => 'picking_status',
     917                                        'compare' => 'NOT EXISTS',
     918                                    )
     919                                ),
     920                                'order' => 'ASC',
     921                            );
     922
     923                            $pickingDate = get_option('pickingDate');
     924                            if (isset($pickingDate) && !empty($pickingDate)) {
     925                                $args['date_query'] = array(
     926                                    array(
     927                                        'after' => $pickingDate,
     928                                    ),
     929                                );
     930                            }
     931
     932                            $query = new WC_Order_Query($args);
     933                            $shop_orders = $query->get_orders();
     934                            $total_picking_orders = count($shop_orders);
     935
     936                            $open_picking_orders = array();
     937                            foreach ($shop_orders as $total_picking_order) {
     938                                $total_picking_order_id = $total_picking_order->get_id();
     939
     940                                $total_items = 0;
     941                                foreach ($total_picking_order->get_items() as $item_id => $item) {
     942                                    if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
     943                                        $product_id = $item->get_product_id();
     944                                        $product_info = wc_get_product($product_id);
     945                                        $product_type = $product_info->get_type();
     946                                        if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     947                                            $total_items = $total_items + $item->get_quantity();
     948                                        }
     949                                    } else {
     950                                        $total_items = $total_items + $item->get_quantity();
     951                                    }
     952                                }
     953
     954                                $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
     955                                if (empty($lastname)) {
     956                                    $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
     957                                }
     958
     959                                $order_number = $total_picking_order_id;
     960                                $order_prefix = get_option('order_prefix');
     961                                if( isset($order_prefix) && !empty($order_prefix) ){
     962                                    $order_number = $order_prefix . $total_picking_order_id;
     963                                }
     964
     965                                $open_picking_orders[] = array(
     966                                    'orderid' => $total_picking_order_id,
     967                                    'order_number' => $order_number,
     968                                    'date' => substr($total_picking_order->get_date_created(), 5, 5),
     969                                    'items' => $total_items,
     970                                    'total' => $currency_symbol . ' ' . $total_picking_order->get_total(),
     971                                    'lastname' => $lastname,
     972                                    'claimed_by' => get_post_meta($total_picking_order_id, 'user_claimed', true),
     973                                );
     974                            }
     975
     976                            $args = array(
     977                                'status' => $order_statussen,
     978                                'limit' => -1,
     979                                'meta_query' => array(
     980                                    array(
     981                                        'key' => 'picking_status',
     982                                        'value' => 'packing',
     983                                        'compare' => '=',
     984                                    )
     985                                )
     986                            );
     987                            $query = new WC_Order_Query($args);
     988                            $packing_orders = $query->get_orders();
     989                            $total_packing_orders = count($packing_orders);
     990                            $total_backorders = 0;
     991
     992                            if (count($packing_orders) > 0) {
     993                                foreach ($packing_orders as $packing_order) {
     994                                    foreach ($packing_order->get_items() as $item_id => $item) {
     995                                        $backorder = get_post_meta($item_id, 'backorder', true);
     996
     997                                        if ($backorder !== '0' && !empty($backorder)) {
     998                                            $total_backorders++;
     999                                            break;
     1000                                        }
     1001
     1002                                    }
     1003                                }
     1004                            }
     1005
     1006                            $output = array(
     1007                                'total_picking_orders' => (int)$total_picking_orders,
     1008                                'total_packing_orders' => (int)$total_packing_orders,
     1009                                'total_backorders' => (int)$total_backorders,
     1010                                'open_picking_orders' => $open_picking_orders,
     1011                            );
     1012                            wp_send_json($output);
     1013                        } else {
     1014                            echo 'Unknown order id!';
     1015                            exit;
     1016                        }
     1017                    } else {
     1018                        echo 'Missing order id!';
     1019                        exit;
     1020                    }
     1021                } else {
     1022                    header("HTTP/1.1 401 Unauthorized");
     1023                    exit;
     1024                }
     1025            } else {
     1026                header("HTTP/1.1 401 Unauthorized");
     1027                exit;
     1028            }
     1029        }
     1030        exit;
     1031    }
     1032
     1033    public
     1034    function createOrderNote($request)
     1035    {
     1036
     1037        header('Access-Control-Allow-Origin: *');
     1038        header("Access-Control-Allow-Credentials: true");
     1039        header('Access-Control-Allow-Methods: POST');
     1040        header('Access-Control-Max-Age: 1000');
     1041        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');
     1042
     1043        $token = $request->get_param('token');
     1044
     1045        $body = $request->get_body();
     1046        $data = json_decode($body, true);
     1047        $orderid = $data['orderid'];
     1048        $message = $data['message'];
     1049
     1050        if (class_exists('WooCommerce')) {
     1051            if (isset($token)) {
     1052                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     1053                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     1054
     1055                    $Order = wc_get_order($orderid);
     1056                    if (!empty($Order)) {
     1057                        $Order->add_order_note($message, true, false);
     1058                        $Order->save();
     1059
     1060
     1061                        wp_send_json('Order ' . $orderid . ' note created!');
     1062                    } else {
     1063                        wp_send_json('Unknown order ID: ' . $orderid);
     1064                    }
     1065                } else {
     1066                    wp_send_json('Unauthorized');
     1067                    header("HTTP/1.1 401 Unauthorized");
     1068                    exit;
     1069                }
     1070            } else {
     1071                wp_send_json('Unauthorized');
     1072                header("HTTP/1.1 401 Unauthorized");
     1073                exit;
     1074            }
     1075        }
     1076        exit;
     1077    }
     1078
     1079    public
     1080    function createOrder($request)
     1081    {
     1082
     1083        header('Access-Control-Allow-Origin: *');
     1084        header("Access-Control-Allow-Credentials: true");
     1085        header('Access-Control-Allow-Methods: POST');
     1086        header('Access-Control-Max-Age: 1000');
     1087        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');
     1088
     1089        $token          = $request->get_param('token');
     1090        $appuser = $request->get_param('appuser');
     1091        $customer_id = $request->get_param('customer_id');
     1092
     1093        $body = $request->get_body();
     1094        $data = json_decode($body, true);
     1095
     1096        if (class_exists('WooCommerce')) {
     1097            if (isset($token)) {
     1098                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     1099                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     1100
     1101                    $order = wc_create_order();
     1102                    $order->set_customer_id( $customer_id );
     1103                    $order->set_status( 'wc-on-hold', 'Order created by '.ucfirst($appuser).' | Order Picking App | ' );
     1104                    foreach( $data['products'] as $product ){
     1105                        $order->add_product( wc_get_product( $product['product_id'] ), $product['ordered'] );
     1106                    }
     1107                    $order->add_meta_data('_wc_order_attribution_source_type', 'utm');
     1108                    $order->add_meta_data('_wc_order_attribution_utm_source', 'Order Picking App');
     1109                    $order->add_order_note( $data['note'] );
     1110                    $order->calculate_totals();
     1111                    $order->save();
     1112
     1113                    wp_send_json($order->get_id());
     1114                }
     1115                else {
     1116                    wp_send_json('Unauthorized');
     1117                    header("HTTP/1.1 401 Unauthorized");
     1118                    exit;
     1119                }
     1120            } else {
     1121                wp_send_json('Unauthorized');
     1122                header("HTTP/1.1 401 Unauthorized");
     1123                exit;
     1124            }
     1125        }
     1126        exit;
     1127    }
     1128
     1129    public
     1130    function getCustomers($request)
     1131    {
     1132
     1133        header('Access-Control-Allow-Origin: *');
     1134        header("Access-Control-Allow-Methods: GET");
     1135
     1136        $token = $request->get_param('token');
     1137
     1138        $Customers = array();
     1139        if (class_exists('WooCommerce')) {
     1140            if (isset($token)) {
     1141                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     1142                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     1143                    $customer_query = new WP_User_Query(
     1144                        array(
     1145                            'fields' => 'ID',
     1146                        )
     1147                    );
     1148                    foreach ( $customer_query->get_results() as $customer_id ) {
     1149                        $customer = new WC_Customer( $customer_id );
     1150                        $Customers[] = array(
     1151                            'id'        => $customer_id,
     1152                            'company'   => $customer->get_billing_company(),
     1153                            'contact'   => $customer->get_billing_first_name() . ' ' . $customer->get_billing_last_name(),
     1154                        );
     1155                    }
     1156                    wp_send_json($Customers);
     1157                } else {
     1158                    wp_send_json('Unauthorized');
     1159                    header("HTTP/1.1 401 Unauthorized");
     1160                    exit;
     1161                }
     1162            } else {
     1163                wp_send_json('Unauthorized');
     1164                header("HTTP/1.1 401 Unauthorized");
     1165                exit;
     1166            }
     1167        }
     1168        exit;
     1169    }
     1170
     1171    public
     1172    function getOrderProducts($request)
     1173    {
     1174
     1175        header('Access-Control-Allow-Origin: *');
     1176        header("Access-Control-Allow-Methods: GET");
     1177
     1178        $Products = array();
     1179        if (class_exists('WooCommerce')) {
     1180            $picking_amount = $request->get_param('picking_amount');
     1181            $appuser = $request->get_param('appuser');
     1182            $token = $request->get_param('token');
     1183
     1184            $picking_batch = get_option('picking_batch');
     1185            if (!isset($picking_batch) || empty($picking_batch)) {
     1186                $picking_batch = 0;
     1187            }
     1188
     1189            if (isset($token)) {
     1190
     1191                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     1192                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     1193
     1194                    $currency_symbol = get_woocommerce_currency_symbol();
     1195                    $currency_symbol = html_entity_decode($currency_symbol);
     1196
     1197                    $manual_order_assigning = get_option('manual_order_assigning');
     1198
     1199                    $post_status = array('wc-processing');
     1200                    $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
     1201                    if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
     1202                        $post_status = (array)$orderpickingapp_order_status;
     1203                    }
     1204
     1205                    $order_statussen = array();
     1206                    foreach ($post_status as $status) {
     1207                        $order_statussen[] = str_replace('wc-', '', $status);
     1208                    }
     1209
     1210                    $args = array(
     1211                        'status' => $order_statussen,
     1212                        'limit' => -1,
     1213                        'meta_query' => array(
     1214                            'relation' => 'OR',
     1215                            array(
     1216                                'relation' => 'AND',
     1217                                array(
     1218                                    'key' => 'picking_status',
     1219                                    'value' => 'packing',
     1220                                    'compare' => '!=',
     1221                                ),
     1222                                array(
     1223                                    'key' => 'picking_status',
     1224                                    'value' => 'completed',
     1225                                    'compare' => '!=',
     1226                                ),
     1227                            ),
     1228                            array(
     1229                                'key' => 'picking_status',
     1230                                'compare' => 'NOT EXISTS',
     1231                            )
     1232                        ),
     1233                        'order' => 'ASC',
     1234                    );
     1235
     1236                    $pickingDate = get_option('pickingDate');
     1237                    if (isset($pickingDate) && !empty($pickingDate)) {
     1238                        $args['date_query'] = array(
     1239                            array(
     1240                                'after' => $pickingDate,
     1241                            ),
     1242                        );
     1243                    }
     1244
     1245                    $query = new WC_Order_Query($args);
     1246                    $shop_orders = $query->get_orders();
     1247                    $total_picking_orders = count($shop_orders);
     1248                    $ordersClaimed = false;
     1249
     1250                    $disable_product_combining = get_option('disable_product_combining');
     1251
     1252                    $open_picking_orders = array();
     1253                    foreach ($shop_orders as $total_picking_order) {
     1254                        $total_picking_order_id = $total_picking_order->get_id();
     1255
     1256                        $batch_id = get_post_meta($total_picking_order_id, 'batch_id', true);
     1257                        $user_claimed = get_post_meta($total_picking_order_id, 'user_claimed', true);
     1258                        if ((isset($batch_id) && !empty($batch_id)) && (isset($user_claimed) && !empty($user_claimed) && $user_claimed == $appuser)) {
     1259                            $ordersClaimed = true;
     1260                        }
     1261
     1262                        // Manual order assigning
     1263                        if (isset($manual_order_assigning) && $manual_order_assigning == 'yes' && $user_claimed != $appuser) {
     1264                            continue;
     1265                        }
     1266
     1267                        $total_items = 0;
     1268                        foreach ($total_picking_order->get_items() as $item) {
     1269                            $product_id = $item->get_product_id();
     1270                            if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php') && !empty($product_id)) {
     1271                                $product_info = wc_get_product($product_id);
     1272                                $product_type = $product_info->get_type();
     1273                                if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     1274                                    $total_items = $total_items + $item->get_quantity();
     1275                                }
     1276                            } else {
     1277                                $total_items = $total_items + $item->get_quantity();
     1278                            }
     1279                        }
     1280
     1281                        $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
     1282                        if (empty($lastname)) {
     1283                            $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
     1284                        }
     1285
     1286                        $order_number = $total_picking_order_id;
     1287                        $order_prefix = get_option('order_prefix');
     1288                        if( isset($order_prefix) && !empty($order_prefix) ){
     1289                            $order_number = $order_prefix . $total_picking_order_id;
     1290                        }
     1291
     1292                        $open_picking_orders[] = array(
     1293                            'orderid' => $total_picking_order_id,
     1294                            'order_number' => $order_number,
     1295                            'date' => substr($total_picking_order->get_date_created(), 5, 5),
     1296                            'items' => $total_items,
     1297                            'total' => $currency_symbol . ' ' . $total_picking_order->get_total(),
     1298                            'lastname' => $lastname,
     1299                            'claimed_by' => $user_claimed,
     1300                        );
     1301                    }
     1302
     1303                    $orderid = $request->get_param('orderid');
     1304
     1305                    // GET SPECIFIC ORDER
     1306                    if (isset($orderid) && strpos($orderid, 'find_') !== false) {
     1307                        $args['post__in'] = (array)str_replace('find_', '', $orderid);
     1308                        $query = new WC_Order_Query($args);
     1309                        $shop_orders = $query->get_orders();
     1310                    } // GET NEXT ORDER
     1311                    elseif (isset($orderid) && strpos($orderid, 'takeover') === false) {
     1312                        $args['post__not_in'] = range(($orderid - $total_picking_orders), $orderid);
     1313                        $query = new WC_Order_Query($args);
     1314                        $next_shop_orders = $query->get_orders();
     1315                        $next_shop_order = $orderid;
     1316
     1317                        if (count($next_shop_orders) > 0) {
     1318                            $shop_orders = $next_shop_orders;
     1319                        }
     1320                    } elseif (isset($orderid) && strpos($orderid, 'takeover') !== false) {
     1321                        $orderid = str_replace('takeover_', '', $orderid);
     1322                        delete_post_meta($orderid, 'user_claimed');
     1323                        $args['post__in'] = (array)$orderid;
     1324                        $query = new WC_Order_Query($args);
     1325                        $shop_orders = $query->get_orders();
     1326                    }
     1327
     1328                    $args = array(
     1329                        'status' => $order_statussen,
     1330                        'limit' => -1,
     1331                        'meta_query' => array(
     1332                            array(
     1333                                'key' => 'picking_status',
     1334                                'value' => 'packing',
     1335                                'compare' => '=',
     1336                            )
     1337                        )
     1338                    );
     1339                    $query = new WC_Order_Query($args);
     1340                    $packing_orders = $query->get_orders();
     1341                    $total_packing_orders = count($packing_orders);
     1342                    $total_backorders = 0;
     1343
     1344                    if (count($packing_orders) > 0) {
     1345                        foreach ($packing_orders as $packing_order) {
     1346                            foreach ($packing_order->get_items() as $item_id => $item) {
     1347                                $backorder = get_post_meta($item_id, 'backorder', true);
     1348                                if ($backorder !== '0' && !empty($backorder)) {
     1349                                    $total_backorders++;
     1350                                    break;
     1351                                }
     1352
     1353                            }
     1354                        }
     1355                    }
     1356
     1357                    $user_order_claims = array();
     1358                    if (count($shop_orders) > 0) {
     1359
     1360                        if (!$ordersClaimed) {
     1361                            $picking_batch++;
     1362                            update_option('picking_batch', $picking_batch);
     1363                        }
     1364
     1365                        $total_orders = 0;
     1366                        $BatchBoxCharacter = 'A';
     1367                        $BatchBoxCharacterSecond = 'A';
     1368                        foreach ($shop_orders as $shop_order) {
     1369                            $shop_order_id = $shop_order->get_id();
     1370
     1371                            if (isset($next_shop_order) && $shop_order_id <= $next_shop_order) {
     1372                                continue;
     1373                            }
     1374
     1375                            // Custom function to return true/false
     1376                            $skip_order = apply_filters('opa_skip_picking_order', false, $shop_order_id);
     1377                            if ($skip_order) {
     1378                                continue;
     1379                            }
     1380
     1381                            if (!empty($appuser)) {
     1382                                $user_claimed = get_post_meta($shop_order_id, 'user_claimed', true);
     1383
     1384                                // Manual order assigning
     1385                                if (isset($manual_order_assigning) && $manual_order_assigning == 'yes' && $user_claimed != $appuser) {
     1386                                    continue;
     1387                                }
     1388
     1389                                $user_order_claims[] = array(
     1390                                    'orderid' => $shop_order_id,
     1391                                    'appuser' => ucfirst($user_claimed),
     1392                                );
     1393                                if (isset($user_claimed) && !empty($user_claimed) && $user_claimed != $appuser) {
     1394                                    continue;
     1395                                }
     1396                            }
     1397
     1398                            if ($total_orders >= $picking_amount) {
     1399                                break;
     1400                            }
     1401
     1402                            $order = $shop_order;
     1403                            $currency_code = $order->get_currency();
     1404                            $currency_symbol = get_woocommerce_currency_symbol($currency_code);
     1405                            $currency_symbol = html_entity_decode($currency_symbol);
     1406                            foreach ($order->get_items() as $item_id => $item) {
     1407
     1408                                $picking_path = '';
     1409                                $product_picking_locations = array();
     1410                                $picking_location = '';
     1411                                $description = '';
     1412
     1413                                $title = $item->get_name();
     1414                                $product_title = explode(" - ", $title, 2)[0];
     1415
     1416                                // Check if product no longer exist in Woocommerce
     1417                                $product_id = $item->get_product_id();
     1418                                if (!isset($product_id) || empty($product_id)) {
     1419                                    $categories = array('Custom products');
     1420                                    $order_cat_id = '';
     1421                                    $thumbnail = '';
     1422
     1423                                    $description = 'Product don\'t exist in Woocommerce!';
     1424                                    $product_id = $item_id;
     1425                                    $sku = $item_id;
     1426
     1427                                    $price = $item->get_total() / $item->get_quantity();
     1428                                    if (isset($price) && !empty($price)) {
     1429                                        $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
     1430                                    } else {
     1431                                        $price = '-';
     1432                                    }
     1433
     1434                                    $stock = '0';
     1435                                    $quantity = $item->get_quantity();
     1436                                } else {
     1437
     1438                                    $categories = array();
     1439
     1440                                    // YOAST COMPATIBILITY
     1441                                    $primary_product_cat = get_post_meta($product_id, '_yoast_wpseo_primary_product_cat', true);
     1442                                    if (isset($primary_product_cat) && !empty($primary_product_cat)) {
     1443                                        $primary_term = get_term($primary_product_cat);
     1444
     1445                                        if (!empty($primary_term->parent)) {
     1446                                            $categories[] = get_term($primary_term->parent)->name;
     1447                                        }
     1448
     1449                                        $categories[] = get_term($primary_product_cat)->name;
     1450                                    } else {
     1451                                        $categories = wp_get_post_terms($product_id, 'product_cat', array("orderby" => "parent"));
     1452
     1453                                        if (isset($categories) && !empty($categories)) {
     1454                                            $categories = wp_list_pluck($categories, 'name');
     1455                                        }
     1456                                    }
     1457
     1458                                    $categoryHierarchy = array();
     1459                                    $this->productCategories = array();
     1460                                    $product_categories = get_the_terms($product_id, 'product_cat', array('hide_empty' => false));
     1461                                    if (isset($product_categories) && is_array($product_categories)) {
     1462                                        $this->sort_terms_hierarchically($product_categories, $categoryHierarchy);
     1463                                    }
     1464                                    $order_cat_id = end($this->productCategories);
     1465                                    if (count($this->productCategories) > 2) {
     1466                                        $order_cat_id = $this->productCategories[1];
     1467                                    }
     1468
     1469                                    $product_picking_locations = wp_get_post_terms($product_id, 'pickingroute', array("orderby" => "parent"));
     1470                                    if (isset($product_picking_locations) && !empty($product_picking_locations)) {
     1471                                        $order_cat_id = end($product_picking_locations)->term_id;
     1472                                        $product_picking_locations = wp_list_pluck($product_picking_locations, 'name');
     1473
     1474                                        $ordered_product_picking_locations = array_reverse($product_picking_locations);
     1475                                        $picking_location = array_pop($ordered_product_picking_locations);
     1476
     1477                                        $picking_path = implode(' / ', $product_picking_locations);
     1478                                    }
     1479
     1480                                    $thumbnail = get_the_post_thumbnail_url($product_id, 'medium');
     1481
     1482                                    $variation_id = $item->get_variation_id();
     1483
     1484                                    if (isset($variation_id) && !empty($variation_id)) {
     1485                                        $product_info = wc_get_product($variation_id);
     1486                                        $product_details = $product_info->get_data();
     1487                                        $product_id = $variation_id;
     1488                                        $product_parent_id = $product_details['parent_id'];
     1489
     1490                                        $opa_picking_location = get_post_meta($product_id, 'opa_picking_location', true);
     1491                                        if (!empty($opa_picking_location)) {
     1492                                            $order_cat_id = (int)$opa_picking_location;
     1493                                            $picking_path = get_term_parents_list($order_cat_id, 'pickingroute', array(
     1494                                                'separator' => '/',
     1495                                                'link' => false,
     1496                                                'format' => 'name',
     1497                                            ));
     1498                                            if (!is_wp_error($picking_path)) {
     1499                                                if (str_ends_with($picking_path, '/')) {
     1500                                                    $picking_path = substr_replace($picking_path, '', -1);
     1501                                                }
     1502
     1503                                                $pos = strrpos($picking_path, '/');
     1504                                                $picking_location = $pos === false ? $picking_path : substr($picking_path, $pos + 1);
     1505                                            }
     1506                                        }
     1507
     1508                                        $sku = $product_details['sku'];
     1509                                        if (empty($sku)) {
     1510                                            $sku = get_post_meta($product_parent_id, '_sku', true);
     1511                                        }
     1512
     1513                                        if (isset($product_details['image_id']) && !empty($product_details['image_id'])) {
     1514                                            $thumbnail = wp_get_attachment_image_url($product_details['image_id']);
     1515                                        }
     1516
     1517                                        if (empty($sku)) {
     1518                                            $sku = $variation_id;
     1519                                            $barcode = 'no sku / barcode';
     1520                                        } else {
     1521                                            $barcode = $sku;
     1522                                        }
     1523                                    } else {
     1524                                        $product_info = wc_get_product($product_id);
     1525                                        $product_details = $product_info->get_data();
     1526                                        $product_id = $item->get_product_id();
     1527                                        $product_parent_id = $item->get_product_id();
     1528
     1529                                        $sku = $product_details['sku'];
     1530
     1531                                        if (empty($sku)) {
     1532                                            $sku = $product_id;
     1533                                            $barcode = 'no sku / barcode';
     1534                                        } else {
     1535                                            $barcode = $sku;
     1536                                        }
     1537                                    }
     1538
     1539                                    $description = $product_details['short_description'];
     1540
     1541                                    $price = $product_info->get_price();
     1542                                    if (isset($price) && !empty($price)) {
     1543                                        $price = $currency_symbol . ' ' . number_format($product_info->get_price(), 2, ",", ".");
     1544                                    } else {
     1545                                        $price = '-';
     1546                                    }
     1547
     1548                                    $stock = $product_info->get_stock_quantity();
     1549                                    $quantity = $item->get_quantity();
     1550                                }
     1551
     1552                                $description = strip_tags($description, '<p><a><strong><i>');
     1553                                $description = str_replace(array("\r", "\n"), '', $description);
     1554                                if (strlen($description) > 200) {
     1555                                    $description = substr($description, 0, 200) . '...';
     1556                                }
     1557
     1558                                if (isset($product_info)) {
     1559                                    $product_type = $product_info->get_type();
     1560                                    if (in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     1561                                        $custom_product_field_label = ucfirst($product_type);
     1562                                        $custom_product_field = $title;
     1563                                        continue;
     1564                                    }
     1565                                }
     1566
     1567                                $meta_description = '';
     1568                                $item_meta = $item->get_meta_data();
     1569                                if ($item_meta) {
     1570                                    foreach ($item_meta as $meta) {
     1571                                        if (in_array($meta->key, array('_reduced_stock')) || str_contains($meta->key, 'pa_') || is_array($meta->value) || str_contains($meta->key, '_')) {
     1572                                            continue;
     1573                                        }
     1574                                        $meta_description .= '<strong>' . $meta->key . '</strong>: ' . $meta->value . '<br />';
     1575                                    }
     1576                                }
     1577
     1578                                if (!empty($meta_description)) {
     1579                                    $description = $meta_description;
     1580                                }
     1581
     1582                                $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
     1583                                if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
     1584                                    $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
     1585                                }
     1586
     1587                                if (strpos($thumbnail, "?")) {
     1588                                    $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
     1589                                }
     1590                                if (!isset($thumbnail) || empty($thumbnail)) {
     1591                                    $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
     1592                                }
     1593
     1594                                // Fallback for product picking location
     1595                                if (!isset($picking_path) || empty($picking_path)) {
     1596                                    $categories = implode(' / ', $categories);
     1597                                } else {
     1598                                    $categories = $picking_path;
     1599                                }
     1600
     1601                                $orderpickingapp_location_field = get_option('orderpickingapp_location_field');
     1602                                if (isset($orderpickingapp_location_field) && !empty($orderpickingapp_location_field)) {
     1603                                    $categories = get_post_meta($product_parent_id, $orderpickingapp_location_field, true);
     1604                                }
     1605
     1606                                $identifier = $product_id;
     1607                                if (isset($disable_product_combining) && $disable_product_combining == 'yes') {
     1608                                    $identifier = $item_id;
     1609                                }
     1610
     1611                                $product_data = array(
     1612                                    'product_id' => $identifier,
     1613                                    'title' => $title,
     1614                                    'product_title' => $product_title,
     1615                                    'thumbnail' => $thumbnail,
     1616                                    'description' => $description,
     1617                                    'sku' => $sku,
     1618                                    'barcode' => $barcode,
     1619                                    'price' => $price,
     1620                                    'stock' => $stock,
     1621                                    'quantity' => $quantity,
     1622                                    'backorder' => 0,
     1623                                    'type' => $product_type,
     1624                                    'order_cat' => $order_cat_id,
     1625                                    'categories' => $categories,
     1626                                    'picking_path' => $picking_path,
     1627                                    'picking_location' => $picking_location,
     1628                                    'total_picking_orders' => $total_picking_orders,
     1629                                    'total_packing_orders' => $total_packing_orders,
     1630                                    'total_backorders' => $total_backorders,
     1631                                    'open_picking_orders' => $open_picking_orders,
     1632                                    'custom_field_label' => '',
     1633                                    'custom_field' => '',
     1634                                );
     1635
     1636                                if (isset($custom_product_field_label) && !empty($custom_product_field_label)) {
     1637                                    $product_data['custom_field_label'] = $custom_product_field_label;
     1638                                    $product_data['custom_field'] = $custom_product_field;
     1639                                } elseif (isset($orderpickingapp_location_field) && !empty($orderpickingapp_location_field)) {
     1640                                    $product_data['custom_field'] = get_post_meta($product_parent_id, $orderpickingapp_location_field, true);
     1641                                }
     1642
     1643                                if (!isset($Products[$identifier]['ordered'])) {
     1644                                    $product_data['ordered'] = $item->get_quantity();
     1645                                } else {
     1646                                    $Products[$identifier]['ordered'] = $Products[$identifier]['ordered'] + $item->get_quantity();
     1647                                }
     1648
     1649                                if (!isset($Products[$identifier]['unpicked'])) {
     1650                                    $product_data['unpicked'] = $item->get_quantity();
     1651                                } else {
     1652                                    $Products[$identifier]['unpicked'] = $Products[$identifier]['unpicked'] + $item->get_quantity();
     1653                                }
     1654
     1655                                if (empty($product_data['stock'])) {
     1656
     1657                                    $_backorders = get_post_meta($item_id, '_backorders', true);
     1658                                    if ($_backorders == 'yes') {
     1659                                        $product_data['stock'] = '0';
     1660                                    } else {
     1661                                        $product_data['stock'] = $item->get_quantity();
     1662                                    }
     1663                                } else {
     1664                                    $product_data['stock'] = $product_data['stock'] + $item->get_quantity();
     1665                                }
     1666
     1667                                if (isset($Products[$identifier])) {
     1668                                    if (isset($Products[$identifier]['quantity'])) {
     1669                                        $Products[$identifier]['quantity'] += $product_data['quantity'];
     1670                                    } else {
     1671                                        $Products[$identifier] = array(
     1672                                            'quantity' => $product_data['quantity']
     1673                                        );
     1674                                    }
     1675                                } else {
     1676                                    $Products[$identifier] = $product_data;
     1677                                }
     1678
     1679                                if (!isset($Products[$identifier]['orders_list'])) {
     1680                                    $Products[$identifier]['orders_list'] = '';
     1681                                }
     1682
     1683                                $custom_field = apply_filters('opa_custom_order_field', '', $shop_order_id);
     1684
     1685                                $total_items = $order->get_item_count();
     1686                                if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
     1687                                    $total_items = 0;
     1688                                    foreach ($order->get_items() as $item) {
     1689                                        $temp_product_id = $item->get_product_id();
     1690                                        if (!empty($temp_product_id)) {
     1691                                            $product_info = wc_get_product($temp_product_id);
     1692                                            $product_type = $product_info->get_type();
     1693                                            if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     1694                                                $total_items++;
     1695                                            }
     1696                                        }
     1697                                    }
     1698                                }
     1699
     1700                                $customer_note = $order->get_customer_note();
     1701                                $customer_note = apply_filters('orderpickingapp_order_note', $customer_note);
     1702
     1703                                if (!isset($Products[$identifier]['orders_list'])) {
     1704                                    $Products[$identifier] = array(
     1705                                        'orders_list' => '#' . $shop_order_id . ' '
     1706                                    );
     1707                                } else {
     1708                                    $Products[$identifier]['orders_list'] .= '#' . $shop_order_id . ' ';
     1709                                }
     1710
     1711                                $BatchID = get_post_meta($shop_order_id, 'batch_id', true);
     1712                                if (!isset($BatchID) || empty($BatchID)) {
     1713                                    $BatchID = $BatchBoxCharacter . $BatchBoxCharacterSecond . '-' . $picking_batch;
     1714                                }
     1715
     1716                                $fullname = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
     1717                                $lastname = substr($order->get_shipping_first_name(), 0, 1) . '. ' . $order->get_shipping_last_name();
     1718                                if (empty($lastname)) {
     1719                                    $fullname = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
     1720                                    $lastname = substr($order->get_billing_first_name(), 0, 1) . '. ' . $order->get_billing_last_name();
     1721                                }
     1722
     1723                                $order_number = $shop_order_id;
     1724                                $order_prefix = get_option('order_prefix');
     1725                                if( isset($order_prefix) && !empty($order_prefix) ){
     1726                                    $order_number = $order_prefix . $shop_order_id;
     1727                                }
     1728
     1729                                $Products[$identifier]['orders'][] = array(
     1730                                    'orderid' => $shop_order_id,
     1731                                    'order_number' => $order_number,
     1732                                    'date' => substr($order->get_date_created(), 5, 5),
     1733                                    'items' => $total_items,
     1734                                    'product_items' => $item->get_quantity(),
     1735                                    'total' => $currency_symbol . ' ' . $order->get_total(),
     1736                                    'fullname' => $fullname,
     1737                                    'lastname' => $lastname,
     1738                                    'shipping' => $order->get_shipping_method(),
     1739                                    'order_note' => $customer_note,
     1740                                    'custom_field' => $custom_field,
     1741                                    'batch_id' => $BatchID,
     1742                                    'batch_number' => preg_replace("/[^0-9]/", '', $BatchID),
     1743                                    'claimed_by' => get_post_meta($shop_order_id, 'user_claimed', $appuser),
     1744                                );
     1745                            }
     1746
     1747                            // Set user claim
     1748                            if (!empty($appuser)) {
     1749                                $Order = new WC_Order($shop_order_id);
     1750                                $Order->update_meta_data('claimed', 'true');
     1751
     1752                                // Manual order assigning
     1753                                if (!isset($manual_order_assigning) || $manual_order_assigning != 'yes') {
     1754                                    $Order->update_meta_data('user_claimed', $appuser);
     1755                                }
     1756                                $Order->update_meta_data('picking_status', 'picking');
     1757                                $Order->update_meta_data('batch_id', $BatchBoxCharacter . $BatchBoxCharacterSecond . '-' . $picking_batch);
     1758                                $Order->add_order_note('Order Picking App | Order picking started by user: ' . $appuser);
     1759                                $Order->save();
     1760                                $total_orders++;
     1761
     1762                                if ($BatchBoxCharacterSecond == 'Z') {
     1763                                    $BatchBoxCharacter = chr(ord($BatchBoxCharacter) + 1);
     1764                                    $BatchBoxCharacterSecond = 'A';
     1765                                } else {
     1766                                    $BatchBoxCharacterSecond = chr(ord($BatchBoxCharacterSecond) + 1);
     1767                                }
     1768                            }
     1769                        }
     1770                    }
     1771                } else {
     1772                    header("HTTP/1.1 401 Unauthorized");
     1773                    exit;
     1774                }
     1775            } else {
     1776                header("HTTP/1.1 401 Unauthorized");
     1777                exit;
     1778            }
     1779        }
     1780
     1781        $this->log('Retrieving open Woocommerce orders with total amount of ' . count($Products), 'Info');
     1782
     1783        if (isset($Products) && !empty($Products)) {
     1784            wp_send_json(array_values($Products));
     1785        } elseif (isset($user_order_claims) && !empty($user_order_claims)) {
     1786            wp_send_json($user_order_claims);
     1787        } elseif (empty($appuser)) {
     1788            wp_send_json(array(
     1789                'total_picking_orders' => $total_picking_orders,
     1790                'total_packing_orders' => $total_packing_orders,
     1791                'total_backorders' => $total_backorders,
    1421792            ));
    143 
    144             register_rest_route('picking/v1', '/get-order-products', array(
    145                 'methods' => 'GET',
    146                 'callback' => array($this, 'getOrderProducts'),
    147                 'permission_callback' => '__return_true',
    148             ));
    149 
    150             register_rest_route('picking/v1', '/pickinglist', array(
    151                 'methods' => 'GET',
    152                 'callback' => array($this, 'getPickingList'),
    153                 'permission_callback' => '__return_true',
    154             ));
    155 
    156             register_rest_route('picking/v1', '/update-order-products', array(
    157                 'methods' => 'POST',
    158                 'callback' => array($this, 'updateOrderProducts'),
    159                 'permission_callback' => '__return_true',
    160             ));
    161 
    162             register_rest_route('picking/v1', '/reset-order-products', array(
    163                 'methods' => 'GET',
    164                 'callback' => array($this, 'resetOrderProducts'),
    165                 'permission_callback' => '__return_true',
    166             ));
    167 
    168             register_rest_route('picking/v1', '/get-packing-orders', array(
    169                 'methods' => 'GET',
    170                 'callback' => array($this, 'requestPackingOrders'),
    171                 'permission_callback' => '__return_true',
    172             ));
    173 
    174             register_rest_route('picking/v1', '/update-order-status', array(
    175                 'methods' => 'POST',
    176                 'callback' => array($this, 'updateOrderStatus'),
    177                 'permission_callback' => '__return_true',
    178             ));
    179 
    180             register_rest_route('picking/v1', '/create-order-note', array(
    181                 'methods' => 'POST',
    182                 'callback' => array($this, 'createOrderNote'),
    183                 'permission_callback' => '__return_true',
    184             ));
    185 
    186             register_rest_route('picking/v1', '/get-categories', array(
    187                 'methods' => 'GET',
    188                 'callback' => array($this, 'getCategories'),
    189                 'permission_callback' => '__return_true',
    190             ));
    191 
    192             register_rest_route('picking/v1', '/get-product', array(
    193                 'methods' => 'GET',
    194                 'callback' => array($this, 'getProduct'),
    195                 'permission_callback' => '__return_true',
    196             ));
    197             register_rest_route('picking/v1', '/update-product', array(
    198                 'methods' => 'POST',
    199                 'callback' => array($this, 'updateProduct'),
    200                 'permission_callback' => '__return_true',
    201             ));
    202 
    203             register_rest_route('picking/v1', '/reset-picking-orders', array(
    204                 'methods' => 'GET',
    205                 'callback' => array($this, 'resetPickingOrders'),
    206                 'permission_callback' => '__return_true',
    207             ));
    208         }
    209 
    210         public
    211         function getSettings($request)
    212         {
    213 
    214             header('Access-Control-Allow-Origin: *');
    215             header("Access-Control-Allow-Methods: GET");
    216 
    217             $Products = array();
    218             if (class_exists('WooCommerce')) {
    219 
    220                 $token = $request->get_param('token');
    221 
    222                 if (isset($token)) {
    223 
    224                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    225                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    226 
    227                         $post_status = array('wc-processing');
    228                         $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
    229                         if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
    230                             $post_status = (array)$orderpickingapp_order_status;
    231                         }
    232 
    233                         $order_statussen = array();
    234                         foreach ($post_status as $status) {
    235                             $order_statussen[] = str_replace('wc-', '', $status);
    236                         }
    237 
     1793        } else {
     1794            wp_send_json(array());
     1795        }
     1796        header("HTTP/1.1 401 Unauthorized");
     1797        exit;
     1798    }
     1799
     1800    public
     1801    function getPickingList($request)
     1802    {
     1803
     1804        header('Access-Control-Allow-Origin: *');
     1805        header("Access-Control-Allow-Methods: GET");
     1806
     1807        $Products = array();
     1808        if (class_exists('WooCommerce')) {
     1809            $token = $request->get_param('token');
     1810            $status = $request->get_param('status');
     1811
     1812            if (isset($token)) {
     1813
     1814                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     1815                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     1816
     1817                    $post_statuses = array('wc-processing');
     1818                    $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
     1819                    if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
     1820                        $post_statuses = (array)$orderpickingapp_order_status;
     1821                    }
     1822
     1823                    $order_statussen = array();
     1824                    foreach ($post_statuses as $post_status) {
     1825                        $order_statussen[] = str_replace('wc-', '', $post_status);
     1826                    }
     1827
     1828                    if (isset($status) && $status == 'backorders') {
     1829                        $args = array(
     1830                            'status' => $order_statussen,
     1831                            'limit' => -1,
     1832                            'meta_query' => array(
     1833                                'relation' => 'OR',
     1834                                array(
     1835                                    'key' => 'picking_status',
     1836                                    'value' => 'packing',
     1837                                    'compare' => '==',
     1838                                ),
     1839                            ),
     1840                            'order' => 'ASC',
     1841                        );
     1842                    } else {
    2381843                        $args = array(
    2391844                            'status' => $order_statussen,
     
    2611866                            'order' => 'ASC',
    2621867                        );
    263 
    264                         $pickingDate = get_option('pickingDate');
    265                         if (isset($pickingDate) && !empty($pickingDate)) {
    266                             $args['date_query'] = array(
    267                                 array(
    268                                     'after' => $pickingDate,
    269                                 ),
     1868                    }
     1869
     1870                    $pickingDate = get_option('pickingDate');
     1871                    if (isset($pickingDate) && !empty($pickingDate)) {
     1872                        $args['date_query'] = array(
     1873                            array(
     1874                                'after' => $pickingDate,
     1875                            ),
     1876                        );
     1877                    }
     1878
     1879                    $query = new WC_Order_Query($args);
     1880                    $shop_orders = $query->get_orders();
     1881
     1882                    if (count($shop_orders) > 0) {
     1883
     1884                        foreach ($shop_orders as $order) {
     1885                            $contains_backorder_products = false;
     1886
     1887                            $currency_code = $order->get_currency();
     1888                            $currency_symbol = get_woocommerce_currency_symbol($currency_code);
     1889                            $currency_symbol = html_entity_decode($currency_symbol);
     1890
     1891                            $order_id = $order->get_id();
     1892                            $order_datetime = str_replace('T', ' ', substr($order->get_date_created(), 0, 16));
     1893
     1894                            $total_items = $order->get_item_count();
     1895                            if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
     1896                                $total_items = 0;
     1897                                foreach ($order->get_items() as $item_id => $item) {
     1898                                    $product_id = $item->get_product_id();
     1899                                    $product_info = wc_get_product($product_id);
     1900                                    $product_type = $product_info->get_type();
     1901                                    if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     1902                                        $total_items++;
     1903                                    }
     1904                                }
     1905                            }
     1906
     1907                            $lastname = substr($order->get_shipping_first_name(), 0, 1) . '. ' . $order->get_shipping_last_name();
     1908                            if (empty($lastname)) {
     1909                                $lastname = substr($order->get_billing_first_name(), 0, 1) . '. ' . $order->get_billing_last_name();
     1910                            }
     1911
     1912                            $customer_note = $order->get_customer_note();
     1913                            $customer_note = apply_filters('orderpickingapp_order_note', $customer_note);
     1914
     1915                            $custom_field = apply_filters('opa_custom_order_field', '', $order_id);
     1916
     1917                            $order_number = $order_id;
     1918                            $order_prefix = get_option('order_prefix');
     1919                            if( isset($order_prefix) && !empty($order_prefix) ){
     1920                                $order_number = $order_prefix . $order_id;
     1921                            }
     1922
     1923                            $output[$order_id] = array(
     1924                                'orderid' => $order_id,
     1925                                'order_number' => $order_number,
     1926                                'date' => substr($order_datetime, 0, 10),
     1927                                'items' => $total_items,
     1928                                'total' => $currency_symbol . ' ' . $order->get_total(),
     1929                                'lastname' => $lastname,
     1930                                'notes' => $customer_note,
     1931                                'custom_field' => $custom_field,
    2701932                            );
    271                         }
    272 
    273                         $query = new WC_Order_Query($args);
    274                         $picking_orders = $query->get_orders();
    275 
    276                         $total_picking_orders = count($picking_orders);
    277 
    278                         $user_orders = array();
    279                         foreach ($picking_orders as $picking_order) {
    280                             $user_claimed = get_post_meta($picking_order->get_id(), 'user_claimed', true);
    281 
    282                             if (isset($user_claimed) && !empty($user_claimed) ) {
    283                                 if (isset($user_orders[$user_claimed])) {
    284                                     $user_orders[$user_claimed] = $user_orders[$user_claimed] + 1;
     1933
     1934                            foreach ($order->get_items() as $item_id => $item) {
     1935
     1936                                $product_id = $item->get_product_id();
     1937
     1938                                // Skip none backorder items
     1939                                if (isset($status) && $status == 'backorders') {
     1940                                    $backorder = get_post_meta($item_id, 'backorder', true);
     1941                                    if ($backorder !== '0' && !empty($backorder)) {
     1942                                        $contains_backorder_products = true;
     1943                                    } else {
     1944                                        continue;
     1945                                    }
     1946                                }
     1947
     1948                                if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
     1949                                    $product_info = wc_get_product($product_id);
     1950                                    $product_type = $product_info->get_type();
     1951                                    if (in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     1952                                        continue;
     1953                                    }
     1954                                }
     1955
     1956                                $title = $item->get_name();
     1957                                $product_title = explode(" - ", $title, 2)[0];
     1958
     1959                                $thumbnail = get_the_post_thumbnail_url($product_id, 'medium');
     1960
     1961                                $variation_id = $item->get_variation_id();
     1962                                if (isset($variation_id) && !empty($variation_id)) {
     1963                                    $product_info = wc_get_product($variation_id);
     1964                                    $product_details = $product_info->get_data();
     1965
     1966                                    if (isset($product_details['image_id']) && !empty($product_details['image_id'])) {
     1967                                        $thumbnail = wp_get_attachment_image_url($product_details['image_id']);
     1968                                    }
     1969
     1970                                    if (strpos($thumbnail, "?")) {
     1971                                        $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
     1972                                    }
     1973                                    if (!isset($thumbnail) || empty($thumbnail)) {
     1974                                        $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
     1975                                    }
     1976
     1977                                    $product_data = array(
     1978                                        'title' => $title,
     1979                                        'product_title' => $product_title,
     1980                                        'thumbnail' => $thumbnail,
     1981                                        'quantity' => $item->get_quantity(),
     1982                                    );
    2851983                                } else {
    286                                     $user_orders[$user_claimed] = 1;
    287                                 }
    288                             }
    289 
    290                         }
    291 
    292                         $args = array(
    293                             'status' => $order_statussen,
    294                             'limit' => -1,
    295                             'meta_query' => array(
    296                                 array(
    297                                     'key' => 'picking_status',
    298                                     'value' => 'packing',
    299                                     'compare' => '=',
    300                                 )
    301                             ),
    302 
    303                         );
    304                         $query = new WC_Order_Query($args);
    305                         $packing_orders = $query->get_orders();
    306                         $total_packing_orders = count($packing_orders);
    307                         $total_backorders = 0;
    308 
    309                         if (count($packing_orders) > 0) {
    310                             foreach ($packing_orders as $packing_order) {
    311                                 foreach ($packing_order->get_items() as $item_id => $item) {
    312                                     $backorder = get_post_meta($item_id, 'backorder', true);
    313 
    314                                     if ($backorder !== '0' && !empty($backorder)) {
    315                                         $total_backorders++;
    316                                         break;
    317                                     }
    318 
    319                                 }
    320                             }
    321                         }
    322 
    323                         $output = array(
    324                             'total_picking_orders' => (int)$total_picking_orders,
    325                             'total_packing_orders' => (int)$total_packing_orders,
    326                             'total_backorders' => (int)$total_backorders,
    327                             'user_orders' => $user_orders
    328                         );
    329                         wp_send_json($output);
    330                     } else {
    331                         header("HTTP/1.1 401 Unauthorized");
    332                         exit;
     1984                                    $product_info = wc_get_product($product_id);
     1985                                    if (strpos($thumbnail, "?")) {
     1986                                        $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
     1987                                    }
     1988                                    if (!isset($thumbnail) || empty($thumbnail)) {
     1989                                        $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
     1990                                    }
     1991
     1992                                    $product_data = array(
     1993                                        'title' => $title,
     1994                                        'product_title' => $product_title,
     1995                                        'thumbnail' => $thumbnail,
     1996                                        'quantity' => $item->get_quantity(),
     1997                                    );
     1998                                }
     1999
     2000                                $product_data['stock'] = $product_info->get_stock_quantity();
     2001
     2002                                $variation_id = $item->get_variation_id();
     2003                                if (isset($variation_id) && !empty($variation_id)) {
     2004                                    $product_info = wc_get_product($variation_id);
     2005                                    $product_details = $product_info->get_data();
     2006                                    $product_data['product_id'] = $variation_id;
     2007                                    $product_id = $variation_id;
     2008
     2009                                    $sku = $product_details['sku'];
     2010                                    if (empty($sku)) {
     2011                                        $sku = get_post_meta($product_details['parent_id'], '_sku', true);
     2012                                    }
     2013
     2014                                    if (!empty($product_details['short_description'])) {
     2015                                        $product_data['description'] = $product_details['short_description'];
     2016                                    } else {
     2017                                        $product_data['description'] = $product_details['description'];
     2018                                    }
     2019
     2020
     2021                                    $product_data['sku'] = $sku;
     2022                                    $product_data['price'] = get_post_meta($product_id, '_price', true);
     2023
     2024                                    if (empty($product_data['sku'])) {
     2025                                        $product_data['sku'] = $variation_id;
     2026                                    }
     2027                                } elseif (isset($product_id) && !empty($product_id)) {
     2028                                    $product_info = wc_get_product($product_id);
     2029                                    $product_details = $product_info->get_data();
     2030                                    $product_id = $item->get_product_id();
     2031                                    $product_data['product_id'] = $product_id;
     2032
     2033                                    $sku = $product_details['sku'];
     2034                                    if (empty($sku)) {
     2035                                        $sku = get_post_meta($product_id, '_sku', true);
     2036                                    }
     2037
     2038                                    if (!empty($product_details['short_description'])) {
     2039                                        $product_data['description'] = $product_details['short_description'];
     2040                                    } else {
     2041                                        $product_data['description'] = $product_details['description'];
     2042                                    }
     2043
     2044                                    $product_data['sku'] = $sku;
     2045                                    $product_data['price'] = get_post_meta($product_id, '_price', true);
     2046
     2047                                    if (empty($product_data['sku'])) {
     2048                                        $product_data['sku'] = $product_id;
     2049                                    }
     2050                                } else {
     2051                                    $product_data['product_id'] = $item_id;
     2052                                    $product_data['description'] = 'Product don\'t exist in Woocommerce!';
     2053                                    $product_data['sku'] = $item_id;
     2054
     2055                                    $price = $item->get_total() / $item->get_quantity();
     2056                                    if (isset($price) && !empty($price)) {
     2057                                        $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
     2058                                    } else {
     2059                                        $price = '-';
     2060                                    }
     2061                                    $product_data['price'] = $price;
     2062
     2063                                    if (empty($product_data['sku'])) {
     2064                                        $product_data['sku'] = $product_data['product_id'];
     2065                                    }
     2066                                }
     2067
     2068                                $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
     2069                                $barcode = $sku;
     2070                                if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
     2071                                    $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
     2072                                }
     2073                                $product_data['barcode'] = $barcode;
     2074
     2075                                $output[$order_id]['products'][] = $product_data;
     2076                            }
     2077
     2078                            // Remove orders without any backorder products
     2079                            if (isset($status) && $status == 'backorders' && !$contains_backorder_products) {
     2080                                unset($output[$order_id]);
     2081                            }
     2082                        }
    3332083                    }
    3342084                } else {
     
    3362086                    exit;
    3372087                }
     2088            } else {
     2089                header("HTTP/1.1 401 Unauthorized");
     2090                exit;
    3382091            }
    3392092        }
    3402093
    341         public
    342         function updateOrderProducts($request)
    343         {
    344 
    345             header('Access-Control-Allow-Origin: *');
    346             header("Access-Control-Allow-Credentials: true");
    347             header('Access-Control-Allow-Methods: POST');
    348             header('Access-Control-Max-Age: 1000');
    349             header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');
    350 
    351             $body = $request->get_body();
    352             $data = json_decode($body, true);
    353 
    354             if (isset($data[0]['orderid'])) {
    355                 $data = $data[0];
    356             }
    357 
    358             if (class_exists('WooCommerce')) {
    359                 $token = $request->get_param('token');
    360                 if (isset($token)) {
    361                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    362                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    363 
    364                         $currency_symbol = get_woocommerce_currency_symbol();
    365                         $currency_symbol = html_entity_decode($currency_symbol);
    366 
    367                         if (isset($data['products']) && !empty($data['products'])) {
    368 
    369                             $products = json_decode($data['products'], true);
    370 
    371                             // Iterate picked products
    372                             $order_notes_done = array();
    373                             foreach ($products as $product) {
    374 
    375                                 $picked_amount = $product['ordered'] - $product['backorder'];
    376 
    377                                 // Iterate related orders for this product
    378                                 foreach ($product['orders'] as $order) {
    379                                     $Order = new WC_Order($order['orderid']);
    380 
    381                                     if (!in_array($order['orderid'], $order_notes_done)) {
    382                                         $Order->add_order_note('Order Picking App | Order picking completed by ' . $data['appuser'] . '. Order now available for packing.');
    383                                         $Order->update_meta_data('picking_status', $data['status']);
    384                                         $this->log('Order picking completed for order:  ' . $order['orderid'] . ' by ' . $data['appuser'], 'Info');
    385                                         $Order->save();
    386 
    387                                         $order_notes_done[$order['orderid']] = $order['orderid'];
    388                                     }
    389 
    390                                     // Check for existing product inside order
    391                                     foreach ($Order->get_items() as $item_id => $item) {
    392                                         $product_processed_stock = $item->get_quantity();
    393 
    394                                         // Set order item/product status to picked
    395                                         $variation_id = $item->get_variation_id();
    396                                         if (isset($variation_id) && !empty($variation_id)) {
    397                                             $product_id = $variation_id;
    398                                         } else {
    399                                             $product_id = $item->get_product_id();
    400                                         }
    401 
    402                                         if (isset($product_id) && $product_id == $product['product_id']) {
    403                                             if ($product['backorder'] == 0) {
    404                                                 update_post_meta($item_id, 'picking_status', 'completed');
    405                                                 update_post_meta($item_id, 'backorder', '0');
    406                                             } elseif ($picked_amount >= $product_processed_stock) {
    407                                                 $picked_amount = $picked_amount - $product_processed_stock;
    408                                                 update_post_meta($item_id, 'picking_status', 'completed');
    409                                                 update_post_meta($item_id, 'backorder', '0');
    410                                             } else {
    411                                                 update_post_meta($item_id, 'picking_status', 'backorder');
    412                                                 update_post_meta($item_id, 'backorder', $product['backorder']);
    413                                             }
    414                                             break;
    415                                         } elseif ((!isset($product_id) || empty($product_id)) && $item_id == $product['product_id']) {
    416                                             if ($product['backorder'] == 0) {
    417                                                 update_post_meta($item_id, 'picking_status', 'completed');
    418                                                 update_post_meta($item_id, 'backorder', '0');
    419                                             } elseif ($picked_amount >= $product_processed_stock) {
    420                                                 $picked_amount = $picked_amount - $product_processed_stock;
    421                                                 update_post_meta($item_id, 'picking_status', 'completed');
    422                                                 update_post_meta($item_id, 'backorder', '0');
    423                                             } else {
    424                                                 update_post_meta($item_id, 'picking_status', 'backorder');
    425                                                 update_post_meta($item_id, 'backorder', $product['backorder']);
    426                                             }
    427                                             break;
    428                                         }
    429                                     }
    430                                 }
    431                             }
    432                         }
    433 
    434                         $post_status = array('wc-processing');
    435                         $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
    436                         if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
    437                             $post_status = (array)$orderpickingapp_order_status;
    438                         }
    439 
    440                         $order_statussen = array();
    441                         foreach ($post_status as $status) {
    442                             $order_statussen[] = str_replace('wc-', '', $status);
    443                         }
    444 
    445                         $args = array(
    446                             'status' => $order_statussen,
    447                             'limit' => -1,
    448                             'meta_query' => array(
    449                                 'relation' => 'OR',
    450                                 array(
    451                                     'relation' => 'AND',
    452                                     array(
    453                                         'key' => 'picking_status',
    454                                         'value' => 'packing',
    455                                         'compare' => '!=',
    456                                     ),
    457                                     array(
    458                                         'key' => 'picking_status',
    459                                         'value' => 'completed',
    460                                         'compare' => '!=',
    461                                     ),
    462                                 ),
    463                                 array(
    464                                     'key' => 'picking_status',
    465                                     'compare' => 'NOT EXISTS',
    466                                 )
    467                             ),
    468                             'order' => 'ASC',
    469                         );
    470 
    471                         $pickingDate = get_option('pickingDate');
    472                         if (isset($pickingDate) && !empty($pickingDate)) {
    473                             $args['date_query'] = array(
    474                                 array(
    475                                     'after' => $pickingDate,
    476                                 ),
    477                             );
    478                         }
    479 
    480                         $query = new WC_Order_Query($args);
    481                         $shop_orders = $query->get_orders();
    482                         $total_picking_orders = count($shop_orders);
    483 
    484                         $open_picking_orders = array();
    485                         foreach ($shop_orders as $total_picking_order) {
    486                             $total_picking_order_id = $total_picking_order->get_id();
    487 
    488                             $total_items = 0;
    489                             foreach ($total_picking_order->get_items() as $item_id => $item) {
    490                                 $product_id = $item->get_product_id();
    491                                 if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php') && !empty($product_id)) {
    492                                     $product_info = wc_get_product($product_id);
    493                                     $product_type = $product_info->get_type();
    494                                     if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    495                                         $total_items = $total_items + $item->get_quantity();
    496                                     }
    497                                 } else {
    498                                     $total_items = $total_items + $item->get_quantity();
    499                                 }
    500                             }
    501 
    502                             $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
    503                             if (empty($lastname)) {
    504                                 $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
    505                             }
    506 
    507                             $order_number = $total_picking_order_id;
    508                             $order_prefix = get_option('order_prefix');
    509                             if( isset($order_prefix) && !empty($order_prefix) ){
    510                                 $order_number = $order_prefix . $total_picking_order_id;
    511                             }
    512 
    513                             $open_picking_orders[] = array(
    514                                 'orderid' => $total_picking_order_id,
    515                                 'order_number' => $order_number,
    516                                 'date' => substr($total_picking_order->get_date_created(), 5, 5),
    517                                 'items' => $total_items,
    518                                 'total' => $currency_symbol . ' ' . $total_picking_order->get_total(),
    519                                 'lastname' => $lastname,
    520                                 'claimed_by' => get_post_meta($total_picking_order_id, 'user_claimed', true),
    521                             );
    522                         }
    523 
    524                         $args = array(
    525                             'status' => $order_statussen,
    526                             'limit' => -1,
    527                             'meta_query' => array(
    528                                 array(
    529                                     'key' => 'picking_status',
    530                                     'value' => 'packing',
    531                                     'compare' => '=',
    532                                 )
    533                             )
    534                         );
    535                         $query = new WC_Order_Query($args);
    536                         $packing_orders = $query->get_orders();
    537                         $total_packing_orders = count($packing_orders);
    538                         $total_backorders = 0;
    539 
    540                         if (count($packing_orders) > 0) {
    541                             foreach ($packing_orders as $packing_order) {
    542                                 foreach ($packing_order->get_items() as $item_id => $item) {
    543                                     $backorder = get_post_meta($item_id, 'backorder', true);
    544 
    545                                     if ($backorder !== '0' && !empty($backorder)) {
    546                                         $total_backorders++;
    547                                         break;
    548                                     }
    549 
    550                                 }
    551                             }
    552                         }
    553 
    554                         $output = array(
    555                             'total_picking_orders' => (int)$total_picking_orders,
    556                             'total_packing_orders' => (int)$total_packing_orders,
    557                             'total_backorders' => (int)$total_backorders,
    558                             'open_picking_orders' => $open_picking_orders
    559                         );
    560                         wp_send_json($output);
    561                     } else {
    562                         header("HTTP/1.1 401 Unauthorized");
    563                         exit;
    564                     }
     2094        if (isset($output) && !empty($output)) {
     2095            wp_send_json(array_values($output));
     2096        } else {
     2097            wp_send_json(array());
     2098        }
     2099        header("HTTP/1.1 401 Unauthorized");
     2100        exit;
     2101    }
     2102
     2103    public
     2104    function requestPackingOrders($request)
     2105    {
     2106
     2107        header('Access-Control-Allow-Origin: *');
     2108        header("Access-Control-Allow-Methods: GET");
     2109
     2110        $output = array();
     2111        $Products = array();
     2112        if (class_exists('WooCommerce')) {
     2113
     2114            $token = $request->get_param('token');
     2115
     2116            if (isset($token)) {
     2117
     2118                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     2119                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     2120                    $output = $this->getPackingOrders();
    5652121                } else {
    5662122                    header("HTTP/1.1 401 Unauthorized");
    5672123                    exit;
    5682124                }
     2125            } else {
     2126                header("HTTP/1.1 401 Unauthorized");
     2127                exit;
    5692128            }
    570             exit;
    571         }
    572 
    573         public
    574         function resetPickingOrders($request)
    575         {
    576 
    577             header('Access-Control-Allow-Origin: *');
    578             header("Access-Control-Allow-Methods: GET");
    579 
    580             if (class_exists('WooCommerce')) {
    581                 $token = $request->get_param('token');
    582                 $appuser = $request->get_param('appuser');
    583 
    584 
    585                 if (isset($token)) {
    586                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    587                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    588 
    589                         $post_status = array('wc-processing');
    590                         $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
    591                         if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
    592                             $post_status = (array)$orderpickingapp_order_status;
    593                         }
    594 
    595                         $order_statussen = array();
    596                         foreach ($post_status as $status) {
    597                             $order_statussen[] = str_replace('wc-', '', $status);
    598                         }
    599 
    600                         $args = array(
    601                             'status' => $order_statussen,
    602                             'limit' => -1,
    603                             'meta_query' => array(
    604                                 'relation' => 'OR',
    605                                 array(
    606                                     'relation' => 'AND',
    607                                     array(
    608                                         'key' => 'picking_status',
    609                                         'value' => 'packing',
    610                                         'compare' => '!=',
    611                                     ),
    612                                     array(
    613                                         'key' => 'picking_status',
    614                                         'value' => 'completed',
    615                                         'compare' => '!=',
    616                                     ),
    617                                 ),
    618                                 array(
    619                                     'key' => 'picking_status',
    620                                     'compare' => 'NOT EXISTS',
    621                                 )
    622                             ),
    623                             'order' => 'ASC',
    624                         );
    625 
    626                         $pickingDate = get_option('pickingDate');
    627                         if (isset($pickingDate) && !empty($pickingDate)) {
    628                             $args['date_query'] = array(
    629                                 array(
    630                                     'after' => $pickingDate,
    631                                 ),
    632                             );
    633                         }
    634 
    635                         $query = new WC_Order_Query($args);
    636                         $picking_orders = $query->get_orders();
    637 
    638                         foreach ($picking_orders as $picking_order) {
    639                             $picking_order_id = $picking_order->get_id();
    640 
    641                             if (!empty($appuser)) {
    642                                 $user_claimed = get_post_meta($picking_order_id, 'user_claimed', true);
    643                                 if (isset($user_claimed) && !empty($user_claimed) && $user_claimed != $appuser) {
    644                                     continue;
    645                                 }
    646                             }
    647 
    648                             delete_post_meta($picking_order_id, 'picking_status');
    649                             delete_post_meta($picking_order_id, 'user_claimed');
    650                             delete_post_meta($picking_order_id, 'batch_id');
    651                         }
    652 
    653                     } else {
    654                         header("HTTP/1.1 401 Unauthorized");
    655                         exit;
    656                     }
    657                 } else {
    658                     header("HTTP/1.1 401 Unauthorized");
    659                     exit;
    660                 }
    661             }
    662             exit;
    663         }
    664 
    665         public
    666         function resetOrderProducts($request)
    667         {
    668 
    669             header('Access-Control-Allow-Origin: *');
    670             header("Access-Control-Allow-Methods: GET");
    671 
    672             if (class_exists('WooCommerce')) {
    673                 $token = $request->get_param('token');
    674                 $orderid = $request->get_param('orderid');
    675                 $appuser = $request->get_param('appuser');
    676                 if (isset($token)) {
    677                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    678                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    679 
    680                         $currency_symbol = get_woocommerce_currency_symbol();
    681                         $currency_symbol = html_entity_decode($currency_symbol);
    682 
    683                         $Order = new WC_Order($orderid);
    684 
    685                         $Order->add_order_note('Order Picking App | Order picking reset by ' . $appuser . '. Order reset to picking list.');
    686                         delete_post_meta($orderid, 'picking_status');
    687                         $this->log('Order picking reset for order:  ' . $orderid . ' by ' . $appuser, 'Info');
    688 
    689                         foreach ($Order->get_items() as $item_id => $item) {
    690                             delete_post_meta($item_id, 'picking_status');
    691                             delete_post_meta($item_id, 'backorder');
    692                         }
    693 
    694                         $post_status = array('wc-processing');
    695                         $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
    696                         if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
    697                             $post_status = (array)$orderpickingapp_order_status;
    698                         }
    699 
    700                         $order_statussen = array();
    701                         foreach ($post_status as $status) {
    702                             $order_statussen[] = str_replace('wc-', '', $status);
    703                         }
    704 
    705                         $args = array(
    706                             'status' => $order_statussen,
    707                             'limit' => -1,
    708                             'meta_query' => array(
    709                                 'relation' => 'OR',
    710                                 array(
    711                                     'relation' => 'AND',
    712                                     array(
    713                                         'key' => 'picking_status',
    714                                         'value' => 'packing',
    715                                         'compare' => '!=',
    716                                     ),
    717                                     array(
    718                                         'key' => 'picking_status',
    719                                         'value' => 'completed',
    720                                         'compare' => '!=',
    721                                     ),
    722                                 ),
    723                                 array(
    724                                     'key' => 'picking_status',
    725                                     'compare' => 'NOT EXISTS',
    726                                 )
    727                             ),
    728                             'order' => 'ASC',
    729                         );
    730 
    731                         $pickingDate = get_option('pickingDate');
    732                         if (isset($pickingDate) && !empty($pickingDate)) {
    733                             $args['date_query'] = array(
    734                                 array(
    735                                     'after' => $pickingDate,
    736                                 ),
    737                             );
    738                         }
    739 
    740                         $query = new WC_Order_Query($args);
    741                         $shop_orders = $query->get_orders();
    742                         $total_picking_orders = count($shop_orders);
    743 
    744                         $open_picking_orders = array();
    745                         foreach ($shop_orders as $total_picking_order) {
    746                             $total_picking_order_id = $total_picking_order->get_id();
    747 
    748                             $total_items = 0;
    749                             foreach ($total_picking_order->get_items() as $item_id => $item) {
    750                                 if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
    751                                     $product_id = $item->get_product_id();
    752                                     $product_info = wc_get_product($product_id);
    753                                     $product_type = $product_info->get_type();
    754                                     if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    755                                         $total_items = $total_items + $item->get_quantity();
    756                                     }
    757                                 } else {
    758                                     $total_items = $total_items + $item->get_quantity();
    759                                 }
    760                             }
    761 
    762                             $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
    763                             if (empty($lastname)) {
    764                                 $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
    765                             }
    766 
    767                             $order_number = $total_picking_order_id;
    768                             $order_prefix = get_option('order_prefix');
    769                             if( isset($order_prefix) && !empty($order_prefix) ){
    770                                 $order_number = $order_prefix . $total_picking_order_id;
    771                             }
    772 
    773                             $open_picking_orders[] = array(
    774                                 'orderid' => $total_picking_order_id,
    775                                 'order_number' => $order_number,
    776                                 'date' => substr($total_picking_order->get_date_created(), 5, 5),
    777                                 'items' => $total_items,
    778                                 'total' => $currency_symbol . ' ' . $total_picking_order->get_total(),
    779                                 'lastname' => $lastname,
    780                                 'claimed_by' => get_post_meta($total_picking_order_id, 'user_claimed', true),
    781                             );
    782                         }
    783 
    784                         $args = array(
    785                             'status' => $order_statussen,
    786                             'limit' => -1,
    787                             'meta_query' => array(
    788                                 array(
    789                                     'key' => 'picking_status',
    790                                     'value' => 'packing',
    791                                     'compare' => '=',
    792                                 )
    793                             )
    794                         );
    795                         $query = new WC_Order_Query($args);
    796                         $packing_orders = $query->get_orders();
    797                         $total_packing_orders = count($packing_orders);
    798                         $total_backorders = 0;
    799 
    800                         if (count($packing_orders) > 0) {
    801                             foreach ($packing_orders as $packing_order) {
    802                                 foreach ($packing_order->get_items() as $item_id => $item) {
    803                                     $backorder = get_post_meta($item_id, 'backorder', true);
    804 
    805                                     if ($backorder !== '0' && !empty($backorder)) {
    806                                         $total_backorders++;
    807                                         break;
    808                                     }
    809 
    810                                 }
    811                             }
    812                         }
    813 
    814                         $output = array(
    815                             'total_picking_orders' => (int)$total_picking_orders,
    816                             'total_packing_orders' => (int)$total_packing_orders,
    817                             'total_backorders' => (int)$total_backorders,
    818                             'open_picking_orders' => $open_picking_orders
    819                         );
    820                         wp_send_json($output);
    821                     } else {
    822                         header("HTTP/1.1 401 Unauthorized");
    823                         exit;
    824                     }
    825                 } else {
    826                     header("HTTP/1.1 401 Unauthorized");
    827                     exit;
    828                 }
    829             }
    830             exit;
    831         }
    832 
    833         public
    834         function updateOrderStatus($request)
    835         {
    836 
    837             header('Access-Control-Allow-Origin: *');
    838             header("Access-Control-Allow-Credentials: true");
    839             header('Access-Control-Allow-Methods: POST');
    840             header('Access-Control-Max-Age: 1000');
    841             header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');
    842 
    843             $body = $request->get_body();
    844             $data = json_decode($body, true);
    845 
    846             if (isset($data[0]['orderid'])) {
    847                 $data = $data[0];
    848             }
    849 
    850             if (class_exists('WooCommerce')) {
    851 
    852                 $token = $request->get_param('token');
    853                 if (isset($token)) {
    854 
    855                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    856                     $auto_completed_order = get_option('auto_completed_order');
    857                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    858 
    859                         $currency_symbol = get_woocommerce_currency_symbol();
    860                         $currency_symbol = html_entity_decode($currency_symbol);
    861 
    862                         if (isset($data['orderid']) && !empty($data['orderid'])) {
    863                             $Order = new WC_Order($data['orderid']);
    864                             if (!empty($Order)) {
    865 
    866                                 $Order->add_order_note('Order Picking App | Order packing completed by ' . $data['appuser']);
    867                                 $Order->update_meta_data('picking_status', $data['status']);
    868 
    869                                 if (isset($data['status']) && $data['status'] == 'completed' && isset($auto_completed_order) && $auto_completed_order == 'yes') {
    870                                     $Order->update_status('completed');
    871                                 }
    872 
    873                                 $this->log('Order packing completed for order:  ' . $data['orderid'] . ' by ' . $data['appuser'], 'Info');
    874                                 $Order->save();
    875 
    876                                 $post_status = array('wc-processing');
    877                                 $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
    878                                 if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
    879                                     $post_status = (array)$orderpickingapp_order_status;
    880                                 }
    881 
    882                                 $order_statussen = array();
    883                                 foreach ($post_status as $status) {
    884                                     $order_statussen[] = str_replace('wc-', '', $status);
    885                                 }
    886 
    887                                 $args = array(
    888                                     'status' => $order_statussen,
    889                                     'limit' => -1,
    890                                     'meta_query' => array(
    891                                         'relation' => 'OR',
    892                                         array(
    893                                             'relation' => 'AND',
    894                                             array(
    895                                                 'key' => 'picking_status',
    896                                                 'value' => 'packing',
    897                                                 'compare' => '!=',
    898                                             ),
    899                                             array(
    900                                                 'key' => 'picking_status',
    901                                                 'value' => 'completed',
    902                                                 'compare' => '!=',
    903                                             ),
    904                                         ),
    905                                         array(
    906                                             'key' => 'picking_status',
    907                                             'compare' => 'NOT EXISTS',
    908                                         )
    909                                     ),
    910                                     'order' => 'ASC',
    911                                 );
    912 
    913                                 $pickingDate = get_option('pickingDate');
    914                                 if (isset($pickingDate) && !empty($pickingDate)) {
    915                                     $args['date_query'] = array(
    916                                         array(
    917                                             'after' => $pickingDate,
    918                                         ),
    919                                     );
    920                                 }
    921 
    922                                 $query = new WC_Order_Query($args);
    923                                 $shop_orders = $query->get_orders();
    924                                 $total_picking_orders = count($shop_orders);
    925 
    926                                 $open_picking_orders = array();
    927                                 foreach ($shop_orders as $total_picking_order) {
    928                                     $total_picking_order_id = $total_picking_order->get_id();
    929 
    930                                     $total_items = 0;
    931                                     foreach ($total_picking_order->get_items() as $item_id => $item) {
    932                                         if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
    933                                             $product_id = $item->get_product_id();
    934                                             $product_info = wc_get_product($product_id);
    935                                             $product_type = $product_info->get_type();
    936                                             if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    937                                                 $total_items = $total_items + $item->get_quantity();
    938                                             }
    939                                         } else {
    940                                             $total_items = $total_items + $item->get_quantity();
    941                                         }
    942                                     }
    943 
    944                                     $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
    945                                     if (empty($lastname)) {
    946                                         $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
    947                                     }
    948 
    949                                     $order_number = $total_picking_order_id;
    950                                     $order_prefix = get_option('order_prefix');
    951                                     if( isset($order_prefix) && !empty($order_prefix) ){
    952                                         $order_number = $order_prefix . $total_picking_order_id;
    953                                     }
    954 
    955                                     $open_picking_orders[] = array(
    956                                         'orderid' => $total_picking_order_id,
    957                                         'order_number' => $order_number,
    958                                         'date' => substr($total_picking_order->get_date_created(), 5, 5),
    959                                         'items' => $total_items,
    960                                         'total' => $currency_symbol . ' ' . $total_picking_order->get_total(),
    961                                         'lastname' => $lastname,
    962                                         'claimed_by' => get_post_meta($total_picking_order_id, 'user_claimed', true),
    963                                     );
    964                                 }
    965 
    966                                 $args = array(
    967                                     'status' => $order_statussen,
    968                                     'limit' => -1,
    969                                     'meta_query' => array(
    970                                         array(
    971                                             'key' => 'picking_status',
    972                                             'value' => 'packing',
    973                                             'compare' => '=',
    974                                         )
    975                                     )
    976                                 );
    977                                 $query = new WC_Order_Query($args);
    978                                 $packing_orders = $query->get_orders();
    979                                 $total_packing_orders = count($packing_orders);
    980                                 $total_backorders = 0;
    981 
    982                                 if (count($packing_orders) > 0) {
    983                                     foreach ($packing_orders as $packing_order) {
    984                                         foreach ($packing_order->get_items() as $item_id => $item) {
    985                                             $backorder = get_post_meta($item_id, 'backorder', true);
    986 
    987                                             if ($backorder !== '0' && !empty($backorder)) {
    988                                                 $total_backorders++;
    989                                                 break;
    990                                             }
    991 
    992                                         }
    993                                     }
    994                                 }
    995 
    996                                 $output = array(
    997                                     'total_picking_orders' => (int)$total_picking_orders,
    998                                     'total_packing_orders' => (int)$total_packing_orders,
    999                                     'total_backorders' => (int)$total_backorders,
    1000                                     'open_picking_orders' => $open_picking_orders,
    1001                                 );
    1002                                 wp_send_json($output);
    1003                             } else {
    1004                                 echo 'Unknown order id!';
    1005                                 exit;
    1006                             }
    1007                         } else {
    1008                             echo 'Missing order id!';
    1009                             exit;
    1010                         }
    1011                     } else {
    1012                         header("HTTP/1.1 401 Unauthorized");
    1013                         exit;
    1014                     }
    1015                 } else {
    1016                     header("HTTP/1.1 401 Unauthorized");
    1017                     exit;
    1018                 }
    1019             }
    1020             exit;
    1021         }
    1022 
    1023 
    1024         public
    1025         function createOrderNote($request)
    1026         {
    1027 
    1028             header('Access-Control-Allow-Origin: *');
    1029             header("Access-Control-Allow-Credentials: true");
    1030             header('Access-Control-Allow-Methods: POST');
    1031             header('Access-Control-Max-Age: 1000');
    1032             header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');
    1033 
    1034             $token = $request->get_param('token');
    1035 
    1036             $body = $request->get_body();
    1037             $data = json_decode($body, true);
    1038             $orderid = $data['orderid'];
    1039             $message = $data['message'];
    1040 
    1041             if (class_exists('WooCommerce')) {
    1042                 if (isset($token)) {
    1043                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    1044                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    1045 
    1046                         $Order = wc_get_order($orderid);
    1047                         if (!empty($Order)) {
    1048                             $Order->add_order_note($message, true, false);
    1049                             $Order->save();
    1050 
    1051 
    1052                             wp_send_json('Order ' . $orderid . ' note created!');
    1053                         } else {
    1054                             wp_send_json('Unknown order ID: ' . $orderid);
    1055                         }
    1056                     } else {
    1057                         wp_send_json('Unauthorized');
    1058                         header("HTTP/1.1 401 Unauthorized");
    1059                         exit;
    1060                     }
    1061                 } else {
    1062                     wp_send_json('Unauthorized');
    1063                     header("HTTP/1.1 401 Unauthorized");
    1064                     exit;
    1065                 }
    1066             }
    1067             exit;
    1068         }
    1069 
    1070         public
    1071         function getOrderProducts($request)
    1072         {
    1073 
    1074             header('Access-Control-Allow-Origin: *');
    1075             header("Access-Control-Allow-Methods: GET");
    1076 
    1077             $Products = array();
    1078             if (class_exists('WooCommerce')) {
    1079                 $picking_amount = $request->get_param('picking_amount');
    1080                 $appuser = $request->get_param('appuser');
    1081                 $token = $request->get_param('token');
    1082 
    1083                 $picking_batch = get_option('picking_batch');
    1084                 if (!isset($picking_batch) || empty($picking_batch)) {
    1085                     $picking_batch = 0;
    1086                 }
    1087 
    1088                 if (isset($token)) {
    1089 
    1090                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    1091                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    1092 
    1093                         $currency_symbol = get_woocommerce_currency_symbol();
    1094                         $currency_symbol = html_entity_decode($currency_symbol);
    1095 
    1096                         $manual_order_assigning = get_option('manual_order_assigning');
    1097 
    1098                         $post_status = array('wc-processing');
    1099                         $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
    1100                         if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
    1101                             $post_status = (array)$orderpickingapp_order_status;
    1102                         }
    1103 
    1104                         $order_statussen = array();
    1105                         foreach ($post_status as $status) {
    1106                             $order_statussen[] = str_replace('wc-', '', $status);
    1107                         }
    1108 
    1109                         $args = array(
    1110                             'status' => $order_statussen,
    1111                             'limit' => -1,
    1112                             'meta_query' => array(
    1113                                 'relation' => 'OR',
    1114                                 array(
    1115                                     'relation' => 'AND',
    1116                                     array(
    1117                                         'key' => 'picking_status',
    1118                                         'value' => 'packing',
    1119                                         'compare' => '!=',
    1120                                     ),
    1121                                     array(
    1122                                         'key' => 'picking_status',
    1123                                         'value' => 'completed',
    1124                                         'compare' => '!=',
    1125                                     ),
    1126                                 ),
    1127                                 array(
    1128                                     'key' => 'picking_status',
    1129                                     'compare' => 'NOT EXISTS',
    1130                                 )
    1131                             ),
    1132                             'order' => 'ASC',
    1133                         );
    1134 
    1135                         $pickingDate = get_option('pickingDate');
    1136                         if (isset($pickingDate) && !empty($pickingDate)) {
    1137                             $args['date_query'] = array(
    1138                                 array(
    1139                                     'after' => $pickingDate,
    1140                                 ),
    1141                             );
    1142                         }
    1143 
    1144                         $query = new WC_Order_Query($args);
    1145                         $shop_orders = $query->get_orders();
    1146                         $total_picking_orders = count($shop_orders);
    1147                         $ordersClaimed = false;
    1148 
    1149                         $disable_product_combining = get_option('disable_product_combining');
    1150 
    1151                         $open_picking_orders = array();
    1152                         foreach ($shop_orders as $total_picking_order) {
    1153                             $total_picking_order_id = $total_picking_order->get_id();
    1154 
    1155                             $batch_id = get_post_meta($total_picking_order_id, 'batch_id', true);
    1156                             $user_claimed = get_post_meta($total_picking_order_id, 'user_claimed', true);
    1157                             if ((isset($batch_id) && !empty($batch_id)) && (isset($user_claimed) && !empty($user_claimed) && $user_claimed == $appuser)) {
    1158                                 $ordersClaimed = true;
    1159                             }
    1160 
    1161                             // Manual order assigning
    1162                             if (isset($manual_order_assigning) && $manual_order_assigning == 'yes' && $user_claimed != $appuser) {
    1163                                 continue;
    1164                             }
    1165 
    1166                             $total_items = 0;
    1167                             foreach ($total_picking_order->get_items() as $item) {
    1168                                 $product_id = $item->get_product_id();
    1169                                 if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php') && !empty($product_id)) {
    1170                                     $product_info = wc_get_product($product_id);
    1171                                     $product_type = $product_info->get_type();
    1172                                     if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    1173                                         $total_items = $total_items + $item->get_quantity();
    1174                                     }
    1175                                 } else {
    1176                                     $total_items = $total_items + $item->get_quantity();
    1177                                 }
    1178                             }
    1179 
    1180                             $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
    1181                             if (empty($lastname)) {
    1182                                 $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
    1183                             }
    1184 
    1185                             $order_number = $total_picking_order_id;
    1186                             $order_prefix = get_option('order_prefix');
    1187                             if( isset($order_prefix) && !empty($order_prefix) ){
    1188                                 $order_number = $order_prefix . $total_picking_order_id;
    1189                             }
    1190 
    1191                             $open_picking_orders[] = array(
    1192                                 'orderid' => $total_picking_order_id,
    1193                                 'order_number' => $order_number,
    1194                                 'date' => substr($total_picking_order->get_date_created(), 5, 5),
    1195                                 'items' => $total_items,
    1196                                 'total' => $currency_symbol . ' ' . $total_picking_order->get_total(),
    1197                                 'lastname' => $lastname,
    1198                                 'claimed_by' => $user_claimed,
    1199                             );
    1200                         }
    1201 
    1202                         $orderid = $request->get_param('orderid');
    1203 
    1204                         // GET SPECIFIC ORDER
    1205                         if (isset($orderid) && strpos($orderid, 'find_') !== false) {
    1206                             $args['post__in'] = (array)str_replace('find_', '', $orderid);
    1207                             $query = new WC_Order_Query($args);
    1208                             $shop_orders = $query->get_orders();
    1209                         } // GET NEXT ORDER
    1210                         elseif (isset($orderid) && strpos($orderid, 'takeover') === false) {
    1211                             $args['post__not_in'] = range(($orderid - $total_picking_orders), $orderid);
    1212                             $query = new WC_Order_Query($args);
    1213                             $next_shop_orders = $query->get_orders();
    1214                             $next_shop_order = $orderid;
    1215 
    1216                             if (count($next_shop_orders) > 0) {
    1217                                 $shop_orders = $next_shop_orders;
    1218                             }
    1219                         } elseif (isset($orderid) && strpos($orderid, 'takeover') !== false) {
    1220                             $orderid = str_replace('takeover_', '', $orderid);
    1221                             delete_post_meta($orderid, 'user_claimed');
    1222                             $args['post__in'] = (array)$orderid;
    1223                             $query = new WC_Order_Query($args);
    1224                             $shop_orders = $query->get_orders();
    1225                         }
    1226 
    1227                         $args = array(
    1228                             'status' => $order_statussen,
    1229                             'limit' => -1,
    1230                             'meta_query' => array(
    1231                                 array(
    1232                                     'key' => 'picking_status',
    1233                                     'value' => 'packing',
    1234                                     'compare' => '=',
    1235                                 )
    1236                             )
    1237                         );
    1238                         $query = new WC_Order_Query($args);
    1239                         $packing_orders = $query->get_orders();
    1240                         $total_packing_orders = count($packing_orders);
    1241                         $total_backorders = 0;
    1242 
    1243                         if (count($packing_orders) > 0) {
    1244                             foreach ($packing_orders as $packing_order) {
    1245                                 foreach ($packing_order->get_items() as $item_id => $item) {
    1246                                     $backorder = get_post_meta($item_id, 'backorder', true);
    1247                                     if ($backorder !== '0' && !empty($backorder)) {
    1248                                         $total_backorders++;
    1249                                         break;
    1250                                     }
    1251 
    1252                                 }
    1253                             }
    1254                         }
    1255 
    1256                         $user_order_claims = array();
    1257                         if (count($shop_orders) > 0) {
    1258 
    1259                             if (!$ordersClaimed) {
    1260                                 $picking_batch++;
    1261                                 update_option('picking_batch', $picking_batch);
    1262                             }
    1263 
    1264                             $total_orders = 0;
    1265                             $BatchBoxCharacter = 'A';
    1266                             $BatchBoxCharacterSecond = 'A';
    1267                             foreach ($shop_orders as $shop_order) {
    1268                                 $shop_order_id = $shop_order->get_id();
    1269 
    1270                                 if (isset($next_shop_order) && $shop_order_id <= $next_shop_order) {
    1271                                     continue;
    1272                                 }
    1273 
    1274                                 // Custom function to return true/false
    1275                                 $skip_order = apply_filters('opa_skip_picking_order', false, $shop_order_id);
    1276                                 if ($skip_order) {
    1277                                     continue;
    1278                                 }
    1279 
    1280                                 if (!empty($appuser)) {
    1281                                     $user_claimed = get_post_meta($shop_order_id, 'user_claimed', true);
    1282 
    1283                                     // Manual order assigning
    1284                                     if (isset($manual_order_assigning) && $manual_order_assigning == 'yes' && $user_claimed != $appuser) {
    1285                                         continue;
    1286                                     }
    1287 
    1288                                     $user_order_claims[] = array(
    1289                                         'orderid' => $shop_order_id,
    1290                                         'appuser' => ucfirst($user_claimed),
    1291                                     );
    1292                                     if (isset($user_claimed) && !empty($user_claimed) && $user_claimed != $appuser) {
    1293                                         continue;
    1294                                     }
    1295                                 }
    1296 
    1297                                 if ($total_orders >= $picking_amount) {
    1298                                     break;
    1299                                 }
    1300 
    1301                                 $order = $shop_order;
    1302                                 $currency_code = $order->get_currency();
    1303                                 $currency_symbol = get_woocommerce_currency_symbol($currency_code);
    1304                                 $currency_symbol = html_entity_decode($currency_symbol);
    1305                                 foreach ($order->get_items() as $item_id => $item) {
    1306 
    1307                                     $picking_path = '';
    1308                                     $product_picking_locations = array();
    1309                                     $picking_location = '';
    1310                                     $description = '';
    1311 
    1312                                     $title = $item->get_name();
    1313                                     $product_title = explode(" - ", $title, 2)[0];
    1314 
    1315                                     // Check if product no longer exist in Woocommerce
    1316                                     $product_id = $item->get_product_id();
    1317                                     if (!isset($product_id) || empty($product_id)) {
    1318                                         $categories = array('Custom products');
    1319                                         $order_cat_id = '';
    1320                                         $thumbnail = '';
    1321 
    1322                                         $description = 'Product don\'t exist in Woocommerce!';
    1323                                         $product_id = $item_id;
    1324                                         $sku = $item_id;
    1325 
    1326                                         $price = $item->get_total() / $item->get_quantity();
    1327                                         if (isset($price) && !empty($price)) {
    1328                                             $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
    1329                                         } else {
    1330                                             $price = '-';
    1331                                         }
    1332 
    1333                                         $stock = '0';
    1334                                         $quantity = $item->get_quantity();
    1335                                     } else {
    1336 
    1337                                         $categories = array();
    1338 
    1339                                         // YOAST COMPATIBILITY
    1340                                         $primary_product_cat = get_post_meta($product_id, '_yoast_wpseo_primary_product_cat', true);
    1341                                         if (isset($primary_product_cat) && !empty($primary_product_cat)) {
    1342                                             $primary_term = get_term($primary_product_cat);
    1343 
    1344                                             if (!empty($primary_term->parent)) {
    1345                                                 $categories[] = get_term($primary_term->parent)->name;
    1346                                             }
    1347 
    1348                                             $categories[] = get_term($primary_product_cat)->name;
    1349                                         } else {
    1350                                             $categories = wp_get_post_terms($product_id, 'product_cat', array("orderby" => "parent"));
    1351 
    1352                                             if (isset($categories) && !empty($categories)) {
    1353                                                 $categories = wp_list_pluck($categories, 'name');
    1354                                             }
    1355                                         }
    1356 
    1357                                         $categoryHierarchy = array();
    1358                                         $this->productCategories = array();
    1359                                         $product_categories = get_the_terms($product_id, 'product_cat', array('hide_empty' => false));
    1360                                         if (isset($product_categories) && is_array($product_categories)) {
    1361                                             $this->sort_terms_hierarchically($product_categories, $categoryHierarchy);
    1362                                         }
    1363                                         $order_cat_id = end($this->productCategories);
    1364                                         if (count($this->productCategories) > 2) {
    1365                                             $order_cat_id = $this->productCategories[1];
    1366                                         }
    1367 
    1368                                         $product_picking_locations = wp_get_post_terms($product_id, 'pickingroute', array("orderby" => "parent"));
    1369                                         if (isset($product_picking_locations) && !empty($product_picking_locations)) {
    1370                                             $order_cat_id = end($product_picking_locations)->term_id;
    1371                                             $product_picking_locations = wp_list_pluck($product_picking_locations, 'name');
    1372 
    1373                                             $ordered_product_picking_locations = array_reverse($product_picking_locations);
    1374                                             $picking_location = array_pop($ordered_product_picking_locations);
    1375 
    1376                                             $picking_path = implode(' / ', $product_picking_locations);
    1377                                         }
    1378 
    1379                                         $thumbnail = get_the_post_thumbnail_url($product_id, 'medium');
    1380 
    1381                                         $variation_id = $item->get_variation_id();
    1382 
    1383                                         if (isset($variation_id) && !empty($variation_id)) {
    1384                                             $product_info = wc_get_product($variation_id);
    1385                                             $product_details = $product_info->get_data();
    1386                                             $product_id = $variation_id;
    1387                                             $product_parent_id = $product_details['parent_id'];
    1388 
    1389                                             $opa_picking_location = get_post_meta($product_id, 'opa_picking_location', true);
    1390                                             if (!empty($opa_picking_location)) {
    1391                                                 $order_cat_id = (int)$opa_picking_location;
    1392                                                 $picking_path = get_term_parents_list($order_cat_id, 'pickingroute', array(
    1393                                                     'separator' => '/',
    1394                                                     'link' => false,
    1395                                                     'format' => 'name',
    1396                                                 ));
    1397                                                 if (!is_wp_error($picking_path)) {
    1398                                                     if (str_ends_with($picking_path, '/')) {
    1399                                                         $picking_path = substr_replace($picking_path, '', -1);
    1400                                                     }
    1401 
    1402                                                     $pos = strrpos($picking_path, '/');
    1403                                                     $picking_location = $pos === false ? $picking_path : substr($picking_path, $pos + 1);
    1404                                                 }
    1405                                             }
    1406 
    1407                                             $sku = $product_details['sku'];
    1408                                             if (empty($sku)) {
    1409                                                 $sku = get_post_meta($product_parent_id, '_sku', true);
    1410                                             }
    1411 
    1412                                             if (isset($product_details['image_id']) && !empty($product_details['image_id'])) {
    1413                                                 $thumbnail = wp_get_attachment_image_url($product_details['image_id']);
    1414                                             }
    1415 
    1416                                             if (empty($sku)) {
    1417                                                 $sku = $variation_id;
    1418                                                 $barcode = 'no sku / barcode';
    1419                                             } else {
    1420                                                 $barcode = $sku;
    1421                                             }
    1422                                         } else {
    1423                                             $product_info = wc_get_product($product_id);
    1424                                             $product_details = $product_info->get_data();
    1425                                             $product_id = $item->get_product_id();
    1426                                             $product_parent_id = $item->get_product_id();
    1427 
    1428                                             $sku = $product_details['sku'];
    1429 
    1430                                             if (empty($sku)) {
    1431                                                 $sku = $product_id;
    1432                                                 $barcode = 'no sku / barcode';
    1433                                             } else {
    1434                                                 $barcode = $sku;
    1435                                             }
    1436                                         }
    1437 
    1438                                         $description = $product_details['short_description'];
    1439 
    1440                                         $price = $product_info->get_price();
    1441                                         if (isset($price) && !empty($price)) {
    1442                                             $price = $currency_symbol . ' ' . number_format($product_info->get_price(), 2, ",", ".");
    1443                                         } else {
    1444                                             $price = '-';
    1445                                         }
    1446 
    1447                                         $stock = $product_info->get_stock_quantity();
    1448                                         $quantity = $item->get_quantity();
    1449                                     }
    1450 
    1451                                     $description = strip_tags($description, '<p><a><strong><i>');
    1452                                     $description = str_replace(array("\r", "\n"), '', $description);
    1453                                     if (strlen($description) > 200) {
    1454                                         $description = substr($description, 0, 200) . '...';
    1455                                     }
    1456 
    1457                                     if (isset($product_info)) {
    1458                                         $product_type = $product_info->get_type();
    1459                                         if (in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    1460                                             $custom_product_field_label = ucfirst($product_type);
    1461                                             $custom_product_field = $title;
    1462                                             continue;
    1463                                         }
    1464                                     }
    1465 
    1466                                     $meta_description = '';
    1467                                     $item_meta = $item->get_meta_data();
    1468                                     if ($item_meta) {
    1469                                         foreach ($item_meta as $meta) {
    1470                                             if (in_array($meta->key, array('_reduced_stock')) || str_contains($meta->key, 'pa_') || is_array($meta->value) || str_contains($meta->key, '_')) {
    1471                                                 continue;
    1472                                             }
    1473                                             $meta_description .= '<strong>' . $meta->key . '</strong>: ' . $meta->value . '<br />';
    1474                                         }
    1475                                     }
    1476 
    1477                                     if (!empty($meta_description)) {
    1478                                         $description = $meta_description;
    1479                                     }
    1480 
    1481                                     $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
    1482                                     if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
    1483                                         $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
    1484                                     }
    1485 
    1486                                     if (strpos($thumbnail, "?")) {
    1487                                         $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
    1488                                     }
    1489                                     if (!isset($thumbnail) || empty($thumbnail)) {
    1490                                         $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
    1491                                     }
    1492 
    1493                                     // Fallback for product picking location
    1494                                     if (!isset($picking_path) || empty($picking_path)) {
    1495                                         $categories = implode(' / ', $categories);
    1496                                     } else {
    1497                                         $categories = $picking_path;
    1498                                     }
    1499 
    1500                                     $orderpickingapp_location_field = get_option('orderpickingapp_location_field');
    1501                                     if (isset($orderpickingapp_location_field) && !empty($orderpickingapp_location_field)) {
    1502                                         $categories = get_post_meta($product_parent_id, $orderpickingapp_location_field, true);
    1503                                     }
    1504 
    1505                                     $identifier = $product_id;
    1506                                     if (isset($disable_product_combining) && $disable_product_combining == 'yes') {
    1507                                         $identifier = $item_id;
    1508                                     }
    1509 
    1510                                     $product_data = array(
    1511                                         'product_id' => $identifier,
    1512                                         'title' => $title,
    1513                                         'product_title' => $product_title,
    1514                                         'thumbnail' => $thumbnail,
    1515                                         'description' => $description,
    1516                                         'sku' => $sku,
    1517                                         'barcode' => $barcode,
    1518                                         'price' => $price,
    1519                                         'stock' => $stock,
    1520                                         'quantity' => $quantity,
    1521                                         'backorder' => 0,
    1522                                         'type' => $product_type,
    1523                                         'order_cat' => $order_cat_id,
    1524                                         'categories' => $categories,
    1525                                         'picking_path' => $picking_path,
    1526                                         'picking_location' => $picking_location,
    1527                                         'total_picking_orders' => $total_picking_orders,
    1528                                         'total_packing_orders' => $total_packing_orders,
    1529                                         'total_backorders' => $total_backorders,
    1530                                         'open_picking_orders' => $open_picking_orders,
    1531                                         'custom_field_label' => '',
    1532                                         'custom_field' => '',
    1533                                     );
    1534 
    1535                                     if (isset($custom_product_field_label) && !empty($custom_product_field_label)) {
    1536                                         $product_data['custom_field_label'] = $custom_product_field_label;
    1537                                         $product_data['custom_field'] = $custom_product_field;
    1538                                     } elseif (isset($orderpickingapp_location_field) && !empty($orderpickingapp_location_field)) {
    1539                                         $product_data['custom_field'] = get_post_meta($product_parent_id, $orderpickingapp_location_field, true);
    1540                                     }
    1541 
    1542                                     if (!isset($Products[$identifier]['ordered'])) {
    1543                                         $product_data['ordered'] = $item->get_quantity();
    1544                                     } else {
    1545                                         $Products[$identifier]['ordered'] = $Products[$identifier]['ordered'] + $item->get_quantity();
    1546                                     }
    1547 
    1548                                     if (!isset($Products[$identifier]['unpicked'])) {
    1549                                         $product_data['unpicked'] = $item->get_quantity();
    1550                                     } else {
    1551                                         $Products[$identifier]['unpicked'] = $Products[$identifier]['unpicked'] + $item->get_quantity();
    1552                                     }
    1553 
    1554                                     if (empty($product_data['stock'])) {
    1555 
    1556                                         $_backorders = get_post_meta($item_id, '_backorders', true);
    1557                                         if ($_backorders == 'yes') {
    1558                                             $product_data['stock'] = '0';
    1559                                         } else {
    1560                                             $product_data['stock'] = $item->get_quantity();
    1561                                         }
    1562                                     } else {
    1563                                         $product_data['stock'] = $product_data['stock'] + $item->get_quantity();
    1564                                     }
    1565 
    1566                                     if (isset($Products[$identifier])) {
    1567                                         if (isset($Products[$identifier]['quantity'])) {
    1568                                             $Products[$identifier]['quantity'] += $product_data['quantity'];
    1569                                         } else {
    1570                                             $Products[$identifier] = array(
    1571                                                 'quantity' => $product_data['quantity']
    1572                                             );
    1573                                         }
    1574                                     } else {
    1575                                         $Products[$identifier] = $product_data;
    1576                                     }
    1577 
    1578                                     if (!isset($Products[$identifier]['orders_list'])) {
    1579                                         $Products[$identifier]['orders_list'] = '';
    1580                                     }
    1581 
    1582                                     $custom_field = apply_filters('opa_custom_order_field', '', $shop_order_id);
    1583 
    1584                                     $total_items = $order->get_item_count();
    1585                                     if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
    1586                                         $total_items = 0;
    1587                                         foreach ($order->get_items() as $item) {
    1588                                             $temp_product_id = $item->get_product_id();
    1589                                             if (!empty($temp_product_id)) {
    1590                                                 $product_info = wc_get_product($temp_product_id);
    1591                                                 $product_type = $product_info->get_type();
    1592                                                 if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    1593                                                     $total_items++;
    1594                                                 }
    1595                                             }
    1596                                         }
    1597                                     }
    1598 
    1599                                     $customer_note = $order->get_customer_note();
    1600                                     $customer_note = apply_filters('orderpickingapp_order_note', $customer_note);
    1601 
    1602                                     if (!isset($Products[$identifier]['orders_list'])) {
    1603                                         $Products[$identifier] = array(
    1604                                             'orders_list' => '#' . $shop_order_id . ' '
    1605                                         );
    1606                                     } else {
    1607                                         $Products[$identifier]['orders_list'] .= '#' . $shop_order_id . ' ';
    1608                                     }
    1609 
    1610                                     $BatchID = get_post_meta($shop_order_id, 'batch_id', true);
    1611                                     if (!isset($BatchID) || empty($BatchID)) {
    1612                                         $BatchID = $BatchBoxCharacter . $BatchBoxCharacterSecond . '-' . $picking_batch;
    1613                                     }
    1614 
    1615                                     $fullname = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
    1616                                     $lastname = substr($order->get_shipping_first_name(), 0, 1) . '. ' . $order->get_shipping_last_name();
    1617                                     if (empty($lastname)) {
    1618                                         $fullname = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
    1619                                         $lastname = substr($order->get_billing_first_name(), 0, 1) . '. ' . $order->get_billing_last_name();
    1620                                     }
    1621 
    1622                                     $order_number = $shop_order_id;
    1623                                     $order_prefix = get_option('order_prefix');
    1624                                     if( isset($order_prefix) && !empty($order_prefix) ){
    1625                                         $order_number = $order_prefix . $shop_order_id;
    1626                                     }
    1627 
    1628                                     $Products[$identifier]['orders'][] = array(
    1629                                         'orderid' => $shop_order_id,
    1630                                         'order_number' => $order_number,
    1631                                         'date' => substr($order->get_date_created(), 5, 5),
    1632                                         'items' => $total_items,
    1633                                         'product_items' => $item->get_quantity(),
    1634                                         'total' => $currency_symbol . ' ' . $order->get_total(),
    1635                                         'fullname' => $fullname,
    1636                                         'lastname' => $lastname,
    1637                                         'shipping' => $order->get_shipping_method(),
    1638                                         'order_note' => $customer_note,
    1639                                         'custom_field' => $custom_field,
    1640                                         'batch_id' => $BatchID,
    1641                                         'batch_number' => preg_replace("/[^0-9]/", '', $BatchID),
    1642                                         'claimed_by' => get_post_meta($shop_order_id, 'user_claimed', $appuser),
    1643                                     );
    1644                                 }
    1645 
    1646                                 // Set user claim
    1647                                 if (!empty($appuser)) {
    1648                                     $Order = new WC_Order($shop_order_id);
    1649                                     $Order->update_meta_data('claimed', 'true');
    1650 
    1651                                     // Manual order assigning
    1652                                     if (!isset($manual_order_assigning) || $manual_order_assigning != 'yes') {
    1653                                         $Order->update_meta_data('user_claimed', $appuser);
    1654                                     }
    1655                                     $Order->update_meta_data('picking_status', 'picking');
    1656                                     $Order->update_meta_data('batch_id', $BatchBoxCharacter . $BatchBoxCharacterSecond . '-' . $picking_batch);
    1657                                     $Order->add_order_note('Order Picking App | Order picking started by user: ' . $appuser);
    1658                                     $Order->save();
    1659                                     $total_orders++;
    1660 
    1661                                     if ($BatchBoxCharacterSecond == 'Z') {
    1662                                         $BatchBoxCharacter = chr(ord($BatchBoxCharacter) + 1);
    1663                                         $BatchBoxCharacterSecond = 'A';
    1664                                     } else {
    1665                                         $BatchBoxCharacterSecond = chr(ord($BatchBoxCharacterSecond) + 1);
    1666                                     }
    1667                                 }
    1668                             }
    1669                         }
    1670                     } else {
    1671                         header("HTTP/1.1 401 Unauthorized");
    1672                         exit;
    1673                     }
    1674                 } else {
    1675                     header("HTTP/1.1 401 Unauthorized");
    1676                     exit;
    1677                 }
    1678             }
    1679 
    1680             $this->log('Retrieving open Woocommerce orders with total amount of ' . count($Products), 'Info');
    1681 
    1682             if (isset($Products) && !empty($Products)) {
    1683                 wp_send_json(array_values($Products));
    1684             } elseif (isset($user_order_claims) && !empty($user_order_claims)) {
    1685                 wp_send_json($user_order_claims);
    1686             } elseif (empty($appuser)) {
    1687                 wp_send_json(array(
    1688                     'total_picking_orders' => $total_picking_orders,
    1689                     'total_packing_orders' => $total_packing_orders,
    1690                     'total_backorders' => $total_backorders,
    1691                 ));
    1692             } else {
    1693                 wp_send_json(array());
    1694             }
    1695             header("HTTP/1.1 401 Unauthorized");
    1696             exit;
    1697         }
    1698 
    1699         public
    1700         function getPickingList($request)
    1701         {
    1702 
    1703             header('Access-Control-Allow-Origin: *');
    1704             header("Access-Control-Allow-Methods: GET");
    1705 
    1706             $Products = array();
    1707             if (class_exists('WooCommerce')) {
    1708                 $token = $request->get_param('token');
    1709                 $status = $request->get_param('status');
    1710 
    1711                 if (isset($token)) {
    1712 
    1713                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    1714                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    1715 
    1716                         $post_statuses = array('wc-processing');
    1717                         $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
    1718                         if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
    1719                             $post_statuses = (array)$orderpickingapp_order_status;
    1720                         }
    1721 
    1722                         $order_statussen = array();
    1723                         foreach ($post_statuses as $post_status) {
    1724                             $order_statussen[] = str_replace('wc-', '', $post_status);
    1725                         }
    1726 
    1727                         if (isset($status) && $status == 'backorders') {
    1728                             $args = array(
    1729                                 'status' => $order_statussen,
    1730                                 'limit' => -1,
    1731                                 'meta_query' => array(
    1732                                     'relation' => 'OR',
    1733                                     array(
    1734                                         'key' => 'picking_status',
    1735                                         'value' => 'packing',
    1736                                         'compare' => '==',
    1737                                     ),
    1738                                 ),
    1739                                 'order' => 'ASC',
    1740                             );
    1741                         } else {
    1742                             $args = array(
    1743                                 'status' => $order_statussen,
    1744                                 'limit' => -1,
    1745                                 'meta_query' => array(
    1746                                     'relation' => 'OR',
    1747                                     array(
    1748                                         'relation' => 'AND',
    1749                                         array(
    1750                                             'key' => 'picking_status',
    1751                                             'value' => 'packing',
    1752                                             'compare' => '!=',
    1753                                         ),
    1754                                         array(
    1755                                             'key' => 'picking_status',
    1756                                             'value' => 'completed',
    1757                                             'compare' => '!=',
    1758                                         ),
    1759                                     ),
    1760                                     array(
    1761                                         'key' => 'picking_status',
    1762                                         'compare' => 'NOT EXISTS',
    1763                                     )
    1764                                 ),
    1765                                 'order' => 'ASC',
    1766                             );
    1767                         }
    1768 
    1769                         $pickingDate = get_option('pickingDate');
    1770                         if (isset($pickingDate) && !empty($pickingDate)) {
    1771                             $args['date_query'] = array(
    1772                                 array(
    1773                                     'after' => $pickingDate,
    1774                                 ),
    1775                             );
    1776                         }
    1777 
    1778                         $query = new WC_Order_Query($args);
    1779                         $shop_orders = $query->get_orders();
    1780 
    1781                         if (count($shop_orders) > 0) {
    1782 
    1783                             foreach ($shop_orders as $order) {
    1784                                 $contains_backorder_products = false;
    1785 
    1786                                 $currency_code = $order->get_currency();
    1787                                 $currency_symbol = get_woocommerce_currency_symbol($currency_code);
    1788                                 $currency_symbol = html_entity_decode($currency_symbol);
    1789 
    1790                                 $order_id = $order->get_id();
    1791                                 $order_datetime = str_replace('T', ' ', substr($order->get_date_created(), 0, 16));
    1792 
    1793                                 $total_items = $order->get_item_count();
    1794                                 if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
    1795                                     $total_items = 0;
    1796                                     foreach ($order->get_items() as $item_id => $item) {
    1797                                         $product_id = $item->get_product_id();
    1798                                         $product_info = wc_get_product($product_id);
    1799                                         $product_type = $product_info->get_type();
    1800                                         if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    1801                                             $total_items++;
    1802                                         }
    1803                                     }
    1804                                 }
    1805 
    1806                                 $lastname = substr($order->get_shipping_first_name(), 0, 1) . '. ' . $order->get_shipping_last_name();
    1807                                 if (empty($lastname)) {
    1808                                     $lastname = substr($order->get_billing_first_name(), 0, 1) . '. ' . $order->get_billing_last_name();
    1809                                 }
    1810 
    1811                                 $customer_note = $order->get_customer_note();
    1812                                 $customer_note = apply_filters('orderpickingapp_order_note', $customer_note);
    1813 
    1814                                 $custom_field = apply_filters('opa_custom_order_field', '', $order_id);
    1815 
    1816                                 $order_number = $order_id;
    1817                                 $order_prefix = get_option('order_prefix');
    1818                                 if( isset($order_prefix) && !empty($order_prefix) ){
    1819                                     $order_number = $order_prefix . $order_id;
    1820                                 }
    1821 
    1822                                 $output[$order_id] = array(
    1823                                     'orderid' => $order_id,
    1824                                     'order_number' => $order_number,
    1825                                     'date' => substr($order_datetime, 0, 10),
    1826                                     'items' => $total_items,
    1827                                     'total' => $currency_symbol . ' ' . $order->get_total(),
    1828                                     'lastname' => $lastname,
    1829                                     'notes' => $customer_note,
    1830                                     'custom_field' => $custom_field,
    1831                                 );
    1832 
    1833                                 foreach ($order->get_items() as $item_id => $item) {
    1834 
    1835                                     $product_id = $item->get_product_id();
    1836 
    1837                                     // Skip none backorder items
    1838                                     if (isset($status) && $status == 'backorders') {
    1839                                         $backorder = get_post_meta($item_id, 'backorder', true);
    1840                                         if ($backorder !== '0' && !empty($backorder)) {
    1841                                             $contains_backorder_products = true;
    1842                                         } else {
    1843                                             continue;
    1844                                         }
    1845                                     }
    1846 
    1847                                     if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
    1848                                         $product_info = wc_get_product($product_id);
    1849                                         $product_type = $product_info->get_type();
    1850                                         if (in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    1851                                             continue;
    1852                                         }
    1853                                     }
    1854 
    1855                                     $title = $item->get_name();
    1856                                     $product_title = explode(" - ", $title, 2)[0];
    1857 
    1858                                     $thumbnail = get_the_post_thumbnail_url($product_id, 'medium');
    1859 
    1860                                     $variation_id = $item->get_variation_id();
    1861                                     if (isset($variation_id) && !empty($variation_id)) {
    1862                                         $product_info = wc_get_product($variation_id);
    1863                                         $product_details = $product_info->get_data();
    1864 
    1865                                         if (isset($product_details['image_id']) && !empty($product_details['image_id'])) {
    1866                                             $thumbnail = wp_get_attachment_image_url($product_details['image_id']);
    1867                                         }
    1868 
    1869                                         if (strpos($thumbnail, "?")) {
    1870                                             $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
    1871                                         }
    1872                                         if (!isset($thumbnail) || empty($thumbnail)) {
    1873                                             $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
    1874                                         }
    1875 
    1876                                         $product_data = array(
    1877                                             'title' => $title,
    1878                                             'product_title' => $product_title,
    1879                                             'thumbnail' => $thumbnail,
    1880                                             'quantity' => $item->get_quantity(),
    1881                                         );
    1882                                     } else {
    1883                                         $product_info = wc_get_product($product_id);
    1884                                         if (strpos($thumbnail, "?")) {
    1885                                             $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
    1886                                         }
    1887                                         if (!isset($thumbnail) || empty($thumbnail)) {
    1888                                             $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
    1889                                         }
    1890 
    1891                                         $product_data = array(
    1892                                             'title' => $title,
    1893                                             'product_title' => $product_title,
    1894                                             'thumbnail' => $thumbnail,
    1895                                             'quantity' => $item->get_quantity(),
    1896                                         );
    1897                                     }
    1898 
    1899                                     $product_data['stock'] = $product_info->get_stock_quantity();
    1900 
    1901                                     $variation_id = $item->get_variation_id();
    1902                                     if (isset($variation_id) && !empty($variation_id)) {
    1903                                         $product_info = wc_get_product($variation_id);
    1904                                         $product_details = $product_info->get_data();
    1905                                         $product_data['product_id'] = $variation_id;
    1906                                         $product_id = $variation_id;
    1907 
    1908                                         $sku = $product_details['sku'];
    1909                                         if (empty($sku)) {
    1910                                             $sku = get_post_meta($product_details['parent_id'], '_sku', true);
    1911                                         }
    1912 
    1913                                         if (!empty($product_details['short_description'])) {
    1914                                             $product_data['description'] = $product_details['short_description'];
    1915                                         } else {
    1916                                             $product_data['description'] = $product_details['description'];
    1917                                         }
    1918 
    1919 
    1920                                         $product_data['sku'] = $sku;
    1921                                         $product_data['price'] = get_post_meta($product_id, '_price', true);
    1922 
    1923                                         if (empty($product_data['sku'])) {
    1924                                             $product_data['sku'] = $variation_id;
    1925                                         }
    1926                                     } elseif (isset($product_id) && !empty($product_id)) {
    1927                                         $product_info = wc_get_product($product_id);
    1928                                         $product_details = $product_info->get_data();
    1929                                         $product_id = $item->get_product_id();
    1930                                         $product_data['product_id'] = $product_id;
    1931 
    1932                                         $sku = $product_details['sku'];
    1933                                         if (empty($sku)) {
    1934                                             $sku = get_post_meta($product_id, '_sku', true);
    1935                                         }
    1936 
    1937                                         if (!empty($product_details['short_description'])) {
    1938                                             $product_data['description'] = $product_details['short_description'];
    1939                                         } else {
    1940                                             $product_data['description'] = $product_details['description'];
    1941                                         }
    1942 
    1943                                         $product_data['sku'] = $sku;
    1944                                         $product_data['price'] = get_post_meta($product_id, '_price', true);
    1945 
    1946                                         if (empty($product_data['sku'])) {
    1947                                             $product_data['sku'] = $product_id;
    1948                                         }
    1949                                     } else {
    1950                                         $product_data['product_id'] = $item_id;
    1951                                         $product_data['description'] = 'Product don\'t exist in Woocommerce!';
    1952                                         $product_data['sku'] = $item_id;
    1953 
    1954                                         $price = $item->get_total() / $item->get_quantity();
    1955                                         if (isset($price) && !empty($price)) {
    1956                                             $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
    1957                                         } else {
    1958                                             $price = '-';
    1959                                         }
    1960                                         $product_data['price'] = $price;
    1961 
    1962                                         if (empty($product_data['sku'])) {
    1963                                             $product_data['sku'] = $product_data['product_id'];
    1964                                         }
    1965                                     }
    1966 
    1967                                     $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
    1968                                     $barcode = $sku;
    1969                                     if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
    1970                                         $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
    1971                                     }
    1972                                     $product_data['barcode'] = $barcode;
    1973 
    1974                                     $output[$order_id]['products'][] = $product_data;
    1975                                 }
    1976 
    1977                                 // Remove orders without any backorder products
    1978                                 if (isset($status) && $status == 'backorders' && !$contains_backorder_products) {
    1979                                     unset($output[$order_id]);
    1980                                 }
    1981                             }
    1982                         }
    1983                     } else {
    1984                         header("HTTP/1.1 401 Unauthorized");
    1985                         exit;
    1986                     }
    1987                 } else {
    1988                     header("HTTP/1.1 401 Unauthorized");
    1989                     exit;
    1990                 }
    1991             }
    1992 
    1993             if (isset($output) && !empty($output)) {
    1994                 wp_send_json(array_values($output));
    1995             } else {
    1996                 wp_send_json(array());
    1997             }
    1998             header("HTTP/1.1 401 Unauthorized");
    1999             exit;
    2000         }
    2001 
    2002         public
    2003         function requestPackingOrders($request)
    2004         {
    2005 
    2006             header('Access-Control-Allow-Origin: *');
    2007             header("Access-Control-Allow-Methods: GET");
    2008 
    2009             $output = array();
    2010             $Products = array();
    2011             if (class_exists('WooCommerce')) {
    2012 
    2013                 $token = $request->get_param('token');
    2014 
    2015                 if (isset($token)) {
    2016 
    2017                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    2018                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    2019                         $output = $this->getPackingOrders();
    2020                     } else {
    2021                         header("HTTP/1.1 401 Unauthorized");
    2022                         exit;
    2023                     }
    2024                 } else {
    2025                     header("HTTP/1.1 401 Unauthorized");
    2026                     exit;
    2027                 }
    2028             }
    2029 
    2030             $this->log('Retrieving open Woocommerce orders with total amount of ' . count($Products), 'Info');
    2031             wp_send_json($output);
    2032             http_response_code(200);
    2033             exit;
    2034         }
    2035 
    2036         public
    2037         function getPackingOrders($return = 'json')
    2038         {
    2039             $post_status = array('wc-processing');
    2040             $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
    2041             if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
    2042                 $post_status = (array)$orderpickingapp_order_status;
    2043             }
    2044 
    2045             $currency_symbol = get_woocommerce_currency_symbol();
    2046             $currency_symbol = html_entity_decode($currency_symbol);
    2047 
    2048             $order_statussen = array();
    2049             foreach ($post_status as $status) {
    2050                 $order_statussen[] = str_replace('wc-', '', $status);
    2051             }
    2052 
    2053             $args = array(
    2054                 'status' => $order_statussen,
    2055                 'limit' => -1,
    2056                 'meta_query' => array(
    2057                     'relation' => 'OR',
     2129        }
     2130
     2131        $this->log('Retrieving open Woocommerce orders with total amount of ' . count($Products), 'Info');
     2132        wp_send_json($output);
     2133        http_response_code(200);
     2134        exit;
     2135    }
     2136
     2137    public
     2138    function getPackingOrders($return = 'json')
     2139    {
     2140        $post_status = array('wc-processing');
     2141        $orderpickingapp_order_status = get_option('orderpickingapp_order_status');
     2142        if (isset($orderpickingapp_order_status) && !empty($orderpickingapp_order_status)) {
     2143            $post_status = (array)$orderpickingapp_order_status;
     2144        }
     2145
     2146        $currency_symbol = get_woocommerce_currency_symbol();
     2147        $currency_symbol = html_entity_decode($currency_symbol);
     2148
     2149        $order_statussen = array();
     2150        foreach ($post_status as $status) {
     2151            $order_statussen[] = str_replace('wc-', '', $status);
     2152        }
     2153
     2154        $args = array(
     2155            'status' => $order_statussen,
     2156            'limit' => -1,
     2157            'meta_query' => array(
     2158                'relation' => 'OR',
     2159                array(
     2160                    'relation' => 'AND',
    20582161                    array(
    2059                         'relation' => 'AND',
    2060                         array(
    2061                             'key' => 'picking_status',
    2062                             'value' => 'packing',
    2063                             'compare' => '!=',
    2064                         ),
    2065                         array(
    2066                             'key' => 'picking_status',
    2067                             'value' => 'completed',
    2068                             'compare' => '!=',
    2069                         ),
     2162                        'key' => 'picking_status',
     2163                        'value' => 'packing',
     2164                        'compare' => '!=',
    20702165                    ),
    20712166                    array(
    20722167                        'key' => 'picking_status',
    2073                         'compare' => 'NOT EXISTS',
    2074                     )
     2168                        'value' => 'completed',
     2169                        'compare' => '!=',
     2170                    ),
    20752171                ),
    2076                 'order' => 'ASC',
     2172                array(
     2173                    'key' => 'picking_status',
     2174                    'compare' => 'NOT EXISTS',
     2175                )
     2176            ),
     2177            'order' => 'ASC',
     2178        );
     2179
     2180        $pickingDate = get_option('pickingDate');
     2181        if (isset($pickingDate) && !empty($pickingDate)) {
     2182            $args['date_query'] = array(
     2183                array(
     2184                    'after' => $pickingDate,
     2185                ),
    20772186            );
    2078 
    2079             $pickingDate = get_option('pickingDate');
    2080             if (isset($pickingDate) && !empty($pickingDate)) {
    2081                 $args['date_query'] = array(
    2082                     array(
    2083                         'after' => $pickingDate,
    2084                     ),
    2085                 );
    2086             }
    2087             $query = new WC_Order_Query($args);
    2088             $picking_orders = $query->get_orders();
    2089             $total_picking_orders = count($picking_orders);
    2090 
    2091             $args = array(
    2092                 'status' => $order_statussen,
    2093                 'limit' => -1,
    2094                 'meta_query' => array(
    2095                     array(
    2096                         'key' => 'picking_status',
    2097                         'value' => 'packing',
    2098                         'compare' => '=',
    2099                     )
    2100                 ),
    2101                 'orderby' => 'date',
    2102                 'order' => 'ASC'
    2103             );
    2104             $query = new WC_Order_Query($args);
    2105             $packing_orders = $query->get_orders();
    2106             $total_packing_orders = count($packing_orders);
    2107             $total_backorders = 0;
    2108 
    2109             if (count($packing_orders) > 0) {
    2110                 foreach ($packing_orders as $packing_order) {
    2111                     foreach ($packing_order->get_items() as $item_id => $item) {
    2112                         $backorder = get_post_meta($item_id, 'backorder', true);
    2113 
    2114                         if ($backorder !== '0' && !empty($backorder)) {
    2115                             $total_backorders++;
    2116                             break;
    2117                         }
    2118 
    2119                     }
     2187        }
     2188        $query = new WC_Order_Query($args);
     2189        $picking_orders = $query->get_orders();
     2190        $total_picking_orders = count($picking_orders);
     2191
     2192        $args = array(
     2193            'status' => $order_statussen,
     2194            'limit' => -1,
     2195            'meta_query' => array(
     2196                array(
     2197                    'key' => 'picking_status',
     2198                    'value' => 'packing',
     2199                    'compare' => '=',
     2200                )
     2201            ),
     2202            'orderby' => 'date',
     2203            'order' => 'ASC'
     2204        );
     2205        $query = new WC_Order_Query($args);
     2206        $packing_orders = $query->get_orders();
     2207        $total_packing_orders = count($packing_orders);
     2208        $total_backorders = 0;
     2209
     2210        if (count($packing_orders) > 0) {
     2211            foreach ($packing_orders as $packing_order) {
     2212                foreach ($packing_order->get_items() as $item_id => $item) {
     2213                    $backorder = get_post_meta($item_id, 'backorder', true);
     2214
     2215                    if ($backorder !== '0' && !empty($backorder)) {
     2216                        $total_backorders++;
     2217                        break;
     2218                    }
     2219
    21202220                }
    21212221            }
    2122 
    2123             if (count($packing_orders) > 0) {
    2124                 foreach ($packing_orders as $order) {
    2125                     $packing_order_id = $order->get_id();
    2126                     $order_datetime = str_replace('T', ' ', substr($order->get_date_created(), 0, 16));
    2127 
    2128                     $customer_note = $order->get_customer_note();
    2129                     $customer_note = apply_filters('orderpickingapp_order_note', $customer_note);
    2130 
    2131                     $total_items = $order->get_item_count();
     2222        }
     2223
     2224        if (count($packing_orders) > 0) {
     2225            foreach ($packing_orders as $order) {
     2226                $packing_order_id = $order->get_id();
     2227                $order_datetime = str_replace('T', ' ', substr($order->get_date_created(), 0, 16));
     2228
     2229                $customer_note = $order->get_customer_note();
     2230                $customer_note = apply_filters('orderpickingapp_order_note', $customer_note);
     2231
     2232                $total_items = $order->get_item_count();
     2233                if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
     2234                    $total_items = 0;
     2235                    foreach ($order->get_items() as $item_id => $item) {
     2236                        $product_id = $item->get_product_id();
     2237                        $product_info = wc_get_product($product_id);
     2238                        $product_type = $product_info->get_type();
     2239                        if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     2240                            $total_items++;
     2241                        }
     2242                    }
     2243                }
     2244
     2245                $fullname = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
     2246                $lastname = substr($order->get_shipping_first_name(), 0, 1) . '. ' . $order->get_shipping_last_name();
     2247                if (empty($lastname)) {
     2248                    $fullname = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
     2249                    $lastname = substr($order->get_billing_first_name(), 0, 1) . '. ' . $order->get_billing_last_name();
     2250                }
     2251
     2252                $order_number = $packing_order_id;
     2253                $order_prefix = get_option('order_prefix');
     2254                if( isset($order_prefix) && !empty($order_prefix) ){
     2255                    $order_number = $order_prefix . $packing_order_id;
     2256                }
     2257
     2258                $output[$packing_order_id] = array(
     2259                    'orderid' => $packing_order_id,
     2260                    'order_number' => $order_number,
     2261                    'datetime' => $order_datetime,
     2262                    'date' => substr($order_datetime, 5, 5),
     2263                    'items' => $total_items,
     2264                    'shipping' => $order->get_shipping_method(),
     2265                    'total' => $currency_symbol . ' ' . $order->get_total(),
     2266                    'notes' => $customer_note,
     2267                    'fullname' => $fullname,
     2268                    'lastname' => $lastname,
     2269                    'onbackorder' => 'false',
     2270                    'batch_id' => get_post_meta($packing_order_id, 'batch_id', true),
     2271                    'total_packing_orders' => $total_packing_orders,
     2272                    'total_picking_orders' => $total_picking_orders,
     2273                    'total_backorders' => $total_backorders,
     2274                );
     2275
     2276                foreach ($order->get_items() as $item_id => $item) {
     2277
     2278                    $product_id = $item->get_product_id();
     2279
    21322280                    if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
    2133                         $total_items = 0;
    2134                         foreach ($order->get_items() as $item_id => $item) {
    2135                             $product_id = $item->get_product_id();
    2136                             $product_info = wc_get_product($product_id);
    2137                             $product_type = $product_info->get_type();
    2138                             if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    2139                                 $total_items++;
    2140                             }
    2141                         }
    2142                     }
    2143 
    2144                     $fullname = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
    2145                     $lastname = substr($order->get_shipping_first_name(), 0, 1) . '. ' . $order->get_shipping_last_name();
    2146                     if (empty($lastname)) {
    2147                         $fullname = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
    2148                         $lastname = substr($order->get_billing_first_name(), 0, 1) . '. ' . $order->get_billing_last_name();
    2149                     }
    2150 
    2151                     $order_number = $packing_order_id;
    2152                     $order_prefix = get_option('order_prefix');
    2153                     if( isset($order_prefix) && !empty($order_prefix) ){
    2154                         $order_number = $order_prefix . $packing_order_id;
    2155                     }
    2156 
    2157                     $output[$packing_order_id] = array(
    2158                         'orderid' => $packing_order_id,
    2159                         'order_number' => $order_number,
    2160                         'datetime' => $order_datetime,
    2161                         'date' => substr($order_datetime, 5, 5),
    2162                         'items' => $total_items,
    2163                         'shipping' => $order->get_shipping_method(),
    2164                         'total' => $currency_symbol . ' ' . $order->get_total(),
    2165                         'notes' => $customer_note,
    2166                         'fullname' => $fullname,
    2167                         'lastname' => $lastname,
    2168                         'onbackorder' => 'false',
    2169                         'batch_id' => get_post_meta($packing_order_id, 'batch_id', true),
    2170                         'total_packing_orders' => $total_packing_orders,
    2171                         'total_picking_orders' => $total_picking_orders,
    2172                         'total_backorders' => $total_backorders,
    2173                     );
    2174 
    2175                     foreach ($order->get_items() as $item_id => $item) {
    2176 
     2281                        $product_info = wc_get_product($product_id);
     2282                        $product_type = $product_info->get_type();
     2283                        if (in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
     2284                            continue;
     2285                        }
     2286                    }
     2287
     2288                    $title = $item->get_name();
     2289                    $product_title = explode(" - ", $title, 2)[0];
     2290
     2291                    $thumbnail = get_the_post_thumbnail_url($product_id, 'medium');
     2292
     2293                    $variation_id = $item->get_variation_id();
     2294                    if (isset($variation_id) && !empty($variation_id)) {
     2295                        $product_info = wc_get_product($variation_id);
     2296                        $product_details = $product_info->get_data();
     2297
     2298                        if (isset($product_details['image_id']) && !empty($product_details['image_id'])) {
     2299                            $thumbnail = wp_get_attachment_image_url($product_details['image_id']);
     2300                        }
     2301
     2302                        if (strpos($thumbnail, "?")) {
     2303                            $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
     2304                        }
     2305                        if (!isset($thumbnail) || empty($thumbnail)) {
     2306                            $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
     2307                        }
     2308
     2309                        $product_data = array(
     2310                            'title' => $title,
     2311                            'product_title' => $product_title,
     2312                            'thumbnail' => $thumbnail,
     2313                            'quantity' => $item->get_quantity(),
     2314                            'status' => get_post_meta($item_id, 'picking_status', true),
     2315                            'backorder' => get_post_meta($item_id, 'backorder', true),
     2316                        );
     2317                    } else {
     2318
     2319
     2320                        if (strpos($thumbnail, "?")) {
     2321                            $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
     2322                        }
     2323                        if (!isset($thumbnail) || empty($thumbnail)) {
     2324                            $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
     2325                        }
     2326
     2327                        $product_data = array(
     2328                            'title' => $title,
     2329                            'product_title' => $product_title,
     2330                            'thumbnail' => $thumbnail,
     2331                            'quantity' => $item->get_quantity(),
     2332                            'status' => get_post_meta($item_id, 'picking_status', true),
     2333                            'backorder' => get_post_meta($item_id, 'backorder', true),
     2334                        );
     2335                    }
     2336
     2337                    if ($product_data['backorder'] !== '0' && !empty($product_data['backorder'])) {
     2338                        $output[$packing_order_id]['onbackorder'] = 'true';
     2339                    }
     2340
     2341                    $variation_id = $item->get_variation_id();
     2342                    if (isset($variation_id) && !empty($variation_id)) {
     2343                        $product_info = wc_get_product($variation_id);
     2344                        $product_details = $product_info->get_data();
     2345                        $product_data['product_id'] = $variation_id;
     2346                        $product_id = $variation_id;
     2347
     2348                        $sku = $product_details['sku'];
     2349                        if (empty($sku)) {
     2350                            $sku = get_post_meta($product_details['parent_id'], '_sku', true);
     2351                        }
     2352
     2353                        if (!empty($product_details['short_description'])) {
     2354                            $product_data['description'] = $product_details['short_description'];
     2355                        } else {
     2356                            $product_data['description'] = $product_details['description'];
     2357                        }
     2358
     2359
     2360                        $product_data['sku'] = $sku;
     2361                        $product_data['price'] = get_post_meta($product_id, '_price', true);
     2362                        $product_data['stock'] = $product_info->get_stock_quantity();
     2363
     2364                        if (empty($product_data['sku'])) {
     2365                            $product_data['sku'] = $variation_id;
     2366                        }
     2367                    } elseif (isset($product_id) && !empty($product_id)) {
     2368                        $product_info = wc_get_product($product_id);
     2369                        $product_details = $product_info->get_data();
    21772370                        $product_id = $item->get_product_id();
    2178 
    2179                         if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
    2180                             $product_info = wc_get_product($product_id);
    2181                             $product_type = $product_info->get_type();
    2182                             if (in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
    2183                                 continue;
    2184                             }
    2185                         }
    2186 
    2187                         $title = $item->get_name();
    2188                         $product_title = explode(" - ", $title, 2)[0];
    2189 
    2190                         $thumbnail = get_the_post_thumbnail_url($product_id, 'medium');
    2191 
    2192                         $variation_id = $item->get_variation_id();
    2193                         if (isset($variation_id) && !empty($variation_id)) {
    2194                             $product_info = wc_get_product($variation_id);
    2195                             $product_details = $product_info->get_data();
    2196 
    2197                             if (isset($product_details['image_id']) && !empty($product_details['image_id'])) {
    2198                                 $thumbnail = wp_get_attachment_image_url($product_details['image_id']);
    2199                             }
    2200 
    2201                             if (strpos($thumbnail, "?")) {
    2202                                 $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
    2203                             }
    2204                             if (!isset($thumbnail) || empty($thumbnail)) {
    2205                                 $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
    2206                             }
    2207 
    2208                             $product_data = array(
    2209                                 'title' => $title,
    2210                                 'product_title' => $product_title,
    2211                                 'thumbnail' => $thumbnail,
    2212                                 'quantity' => $item->get_quantity(),
    2213                                 'status' => get_post_meta($item_id, 'picking_status', true),
    2214                                 'backorder' => get_post_meta($item_id, 'backorder', true),
    2215                             );
     2371                        $product_data['product_id'] = $product_id;
     2372
     2373                        $sku = $product_details['sku'];
     2374                        if (empty($sku)) {
     2375                            $sku = get_post_meta($product_details['$product_id'], '_sku', true);
     2376                        }
     2377
     2378                        if (!empty($product_details['short_description'])) {
     2379                            $product_data['description'] = $product_details['short_description'];
    22162380                        } else {
    2217 
    2218 
    2219                             if (strpos($thumbnail, "?")) {
    2220                                 $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
    2221                             }
    2222                             if (!isset($thumbnail) || empty($thumbnail)) {
    2223                                 $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
    2224                             }
    2225 
    2226                             $product_data = array(
    2227                                 'title' => $title,
    2228                                 'product_title' => $product_title,
    2229                                 'thumbnail' => $thumbnail,
    2230                                 'quantity' => $item->get_quantity(),
    2231                                 'status' => get_post_meta($item_id, 'picking_status', true),
    2232                                 'backorder' => get_post_meta($item_id, 'backorder', true),
    2233                             );
    2234                         }
    2235 
    2236                         if ($product_data['backorder'] !== '0' && !empty($product_data['backorder'])) {
    2237                             $output[$packing_order_id]['onbackorder'] = 'true';
    2238                         }
    2239 
    2240                         $variation_id = $item->get_variation_id();
    2241                         if (isset($variation_id) && !empty($variation_id)) {
    2242                             $product_info = wc_get_product($variation_id);
    2243                             $product_details = $product_info->get_data();
    2244                             $product_data['product_id'] = $variation_id;
    2245                             $product_id = $variation_id;
    2246 
    2247                             $sku = $product_details['sku'];
    2248                             if (empty($sku)) {
    2249                                 $sku = get_post_meta($product_details['parent_id'], '_sku', true);
    2250                             }
    2251 
    2252                             if (!empty($product_details['short_description'])) {
    2253                                 $product_data['description'] = $product_details['short_description'];
    2254                             } else {
    2255                                 $product_data['description'] = $product_details['description'];
    2256                             }
    2257 
    2258 
    2259                             $product_data['sku'] = $sku;
    2260                             $product_data['price'] = get_post_meta($product_id, '_price', true);
    2261                             $product_data['stock'] = $product_info->get_stock_quantity();
    2262 
    2263                             if (empty($product_data['sku'])) {
    2264                                 $product_data['sku'] = $variation_id;
    2265                             }
    2266                         } elseif (isset($product_id) && !empty($product_id)) {
    2267                             $product_info = wc_get_product($product_id);
    2268                             $product_details = $product_info->get_data();
    2269                             $product_id = $item->get_product_id();
    2270                             $product_data['product_id'] = $product_id;
    2271 
    2272                             $sku = $product_details['sku'];
    2273                             if (empty($sku)) {
    2274                                 $sku = get_post_meta($product_details['$product_id'], '_sku', true);
    2275                             }
    2276 
    2277                             if (!empty($product_details['short_description'])) {
    2278                                 $product_data['description'] = $product_details['short_description'];
    2279                             } else {
    2280                                 $product_data['description'] = $product_details['description'];
    2281                             }
    2282 
    2283                             $product_data['sku'] = $sku;
    2284                             $product_data['price'] = get_post_meta($product_id, '_price', true);
    2285                             $product_data['stock'] = $product_info->get_stock_quantity();
    2286 
    2287                             if (empty($product_data['sku'])) {
    2288                                 $product_data['sku'] = $product_id;
    2289                             }
     2381                            $product_data['description'] = $product_details['description'];
     2382                        }
     2383
     2384                        $product_data['sku'] = $sku;
     2385                        $product_data['price'] = get_post_meta($product_id, '_price', true);
     2386                        $product_data['stock'] = $product_info->get_stock_quantity();
     2387
     2388                        if (empty($product_data['sku'])) {
     2389                            $product_data['sku'] = $product_id;
     2390                        }
     2391                    } else {
     2392                        $product_data['product_id'] = $item_id;
     2393                        $product_data['description'] = 'Product don\'t exist in Woocommerce!';
     2394                        $product_data['sku'] = $item_id;
     2395
     2396                        $price = $item->get_total() / $item->get_quantity();
     2397                        if (isset($price) && !empty($price)) {
     2398                            $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
    22902399                        } else {
    2291                             $product_data['product_id'] = $item_id;
    2292                             $product_data['description'] = 'Product don\'t exist in Woocommerce!';
    2293                             $product_data['sku'] = $item_id;
    2294 
    2295                             $price = $item->get_total() / $item->get_quantity();
    2296                             if (isset($price) && !empty($price)) {
    2297                                 $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
    2298                             } else {
    2299                                 $price = '-';
    2300                             }
    2301                             $product_data['price'] = $price;
     2400                            $price = '-';
     2401                        }
     2402                        $product_data['price'] = $price;
     2403                        $product_data['stock'] = $item->get_quantity();
     2404
     2405                        if (empty($product_data['sku'])) {
     2406                            $product_data['sku'] = $product_data['product_id'];
     2407                        }
     2408                    }
     2409
     2410                    $product_data['description'] = strip_tags($product_data['description'], '<p><a><strong><i>');
     2411                    $product_data['description'] = str_replace(array("\r", "\n"), '', $product_data['description']);
     2412                    if (strlen($product_data['description']) > 300) {
     2413                        $product_data['description'] = substr($product_data['description'], 0, 300) . '...';
     2414                    }
     2415
     2416                    // Niet aanwezig in Woocommerce
     2417                    $product_data['product_reference'] = '';
     2418                    $product_data['reference'] = '';
     2419
     2420                    $product_data['ordered'] = $product_data['quantity'];
     2421                    $product_data['unpacked'] = $product_data['quantity'];
     2422
     2423                    if (empty($product_data['stock'])) {
     2424                        $_backorders = get_post_meta($item_id, '_backorders', true);
     2425                        if ($_backorders == 'yes') {
     2426                            $product_data['stock'] = '0';
     2427                        } else {
    23022428                            $product_data['stock'] = $item->get_quantity();
    2303 
    2304                             if (empty($product_data['sku'])) {
    2305                                 $product_data['sku'] = $product_data['product_id'];
    2306                             }
    2307                         }
    2308 
    2309                         $product_data['description'] = strip_tags($product_data['description'], '<p><a><strong><i>');
    2310                         $product_data['description'] = str_replace(array("\r", "\n"), '', $product_data['description']);
    2311                         if (strlen($product_data['description']) > 300) {
    2312                             $product_data['description'] = substr($product_data['description'], 0, 300) . '...';
    2313                         }
    2314 
    2315                         // Niet aanwezig in Woocommerce
    2316                         $product_data['product_reference'] = '';
    2317                         $product_data['reference'] = '';
    2318 
    2319                         $product_data['ordered'] = $product_data['quantity'];
    2320                         $product_data['unpacked'] = $product_data['quantity'];
    2321 
    2322                         if (empty($product_data['stock'])) {
    2323                             $_backorders = get_post_meta($item_id, '_backorders', true);
    2324                             if ($_backorders == 'yes') {
    2325                                 $product_data['stock'] = '0';
    2326                             } else {
    2327                                 $product_data['stock'] = $item->get_quantity();
    2328                             }
    2329                         }
    2330 
    2331                         $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
    2332                         $barcode = $sku;
    2333                         if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
    2334                             $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
    2335                         }
    2336                         $product_data['barcode'] = $barcode;
    2337 
    2338                         $output[$packing_order_id]['products'][] = $product_data;
    2339                     }
    2340                 }
    2341             } else {
    2342                 $output = array(
    2343                     array(
    2344                         'total_picking_orders' => $total_picking_orders,
    2345                         'total_packing_orders' => 0,
    2346                         'total_backorders' => 0,
    2347                     ),
    2348                 );
    2349             }
    2350 
    2351             return $output;
    2352         }
    2353 
    2354         public
    2355         function log($Message, $Type = 'Info')
    2356         {
    2357             fwrite(self::$logFileHandle, date('d-m-Y H:i:s') . " | " . str_pad($Type, 8, " ", STR_PAD_RIGHT) . " | " . $Message . "\n");
    2358         }
    2359 
    2360         public
    2361         function getCategories($output = 'json', $taxonomy = 'product_cat')
    2362         {
    2363 
    2364             header('Access-Control-Allow-Origin: *');
    2365             header("Access-Control-Allow-Methods: GET");
    2366 
    2367             $categories = get_terms($taxonomy, array('hide_empty' => false));
    2368             $categoryHierarchy = array();
    2369 
    2370             if (isset($categories) && !empty($categories)) {
    2371                 $this->sort_terms_hierarchically($categories, $categoryHierarchy);
    2372             }
    2373 
    2374             if ($output == 'json') {
    2375                 echo json_encode($this->orderedCategories);
    2376                 exit;
    2377             }
    2378             return $this->orderedCategories;
    2379         }
    2380 
    2381         public
    2382         function sort_terms_hierarchically(array &$cats, array &$into, $parentId = 0)
    2383         {
    2384             foreach ($cats as $i => $cat) {
    2385                 if ($cat->parent == $parentId) {
    2386                     $into[$cat->term_id] = $cat;
    2387                     if ($parentId == 0) {
    2388                         $this->orderedCategories[$cat->term_id]['name'] = $cat->name;
    2389                         $this->orderedCategories[$cat->term_id]['count'] = $cat->count;
    2390                         $this->orderedCategories[$cat->term_id]['children'] = array();
    2391                         $this->productCategories[] = $cat->term_id;
    2392                     } else {
    2393                         $this->orderedCategories[$parentId]['children'][$cat->term_id] = $cat->name;
    2394                         $this->productCategories[] = $cat->term_id;
    2395                     }
    2396                     unset($cats[$i]);
     2429                        }
     2430                    }
     2431
     2432                    $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
     2433                    $barcode = $sku;
     2434                    if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
     2435                        $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
     2436                    }
     2437                    $product_data['barcode'] = $barcode;
     2438
     2439                    $output[$packing_order_id]['products'][] = $product_data;
    23972440                }
    23982441            }
    2399 
    2400             foreach ($into as $topCat) {
    2401                 $topCat->children = array();
    2402                 $this->sort_terms_hierarchically($cats, $topCat->children, $topCat->term_id);
     2442        } else {
     2443            $output = array(
     2444                array(
     2445                    'total_picking_orders' => $total_picking_orders,
     2446                    'total_packing_orders' => 0,
     2447                    'total_backorders' => 0,
     2448                ),
     2449            );
     2450        }
     2451
     2452        return $output;
     2453    }
     2454
     2455    public
     2456    function log($Message, $Type = 'Info')
     2457    {
     2458        fwrite(self::$logFileHandle, date('d-m-Y H:i:s') . " | " . str_pad($Type, 8, " ", STR_PAD_RIGHT) . " | " . $Message . "\n");
     2459    }
     2460
     2461    public
     2462    function getCategories($output = 'json', $taxonomy = 'product_cat')
     2463    {
     2464
     2465        header('Access-Control-Allow-Origin: *');
     2466        header("Access-Control-Allow-Methods: GET");
     2467
     2468        $categories = get_terms($taxonomy, array('hide_empty' => false));
     2469        $categoryHierarchy = array();
     2470
     2471        if (isset($categories) && !empty($categories)) {
     2472            $this->sort_terms_hierarchically($categories, $categoryHierarchy);
     2473        }
     2474
     2475        if ($output == 'json') {
     2476            echo json_encode($this->orderedCategories);
     2477            exit;
     2478        }
     2479        return $this->orderedCategories;
     2480    }
     2481
     2482    public
     2483    function sort_terms_hierarchically(array &$cats, array &$into, $parentId = 0)
     2484    {
     2485        foreach ($cats as $i => $cat) {
     2486            if ($cat->parent == $parentId) {
     2487                $into[$cat->term_id] = $cat;
     2488                if ($parentId == 0) {
     2489                    $this->orderedCategories[$cat->term_id]['name'] = $cat->name;
     2490                    $this->orderedCategories[$cat->term_id]['count'] = $cat->count;
     2491                    $this->orderedCategories[$cat->term_id]['children'] = array();
     2492                    $this->productCategories[] = $cat->term_id;
     2493                } else {
     2494                    $this->orderedCategories[$parentId]['children'][$cat->term_id] = $cat->name;
     2495                    $this->productCategories[] = $cat->term_id;
     2496                }
     2497                unset($cats[$i]);
    24032498            }
    24042499        }
    24052500
    2406         public
    2407         function downloadLog($data)
    2408         {
    2409             if (isset($data['date'])) {
    2410                 $Day = $data['date'];
    2411                 if (preg_match("/\d{4}-\d{2}-\d{2}/", $Day)) {
    2412                     if (is_dir(self::$logPath)) {
    2413                         if (file_exists(self::$logPath . "/" . $Day . ".log")) {
    2414                             header("Content-Description: File Transfer");
    2415                             header("Content-Type: application/octet-stream");
    2416                             header("Content-Disposition: attachment; filename=" . $Day . ".log");
    2417                             readfile(self::$logPath . "/" . $Day . ".log");
    2418                             exit;
    2419                         } else {
    2420                             $response['Status'] = 'Failed';
    2421                             $response['Message'] = 'Log file for: ' . $Day . ' not found';
    2422                             exit(json_encode($response));
    2423                         }
     2501        foreach ($into as $topCat) {
     2502            $topCat->children = array();
     2503            $this->sort_terms_hierarchically($cats, $topCat->children, $topCat->term_id);
     2504        }
     2505    }
     2506
     2507    public
     2508    function downloadLog($data)
     2509    {
     2510        if (isset($data['date'])) {
     2511            $Day = $data['date'];
     2512            if (preg_match("/\d{4}-\d{2}-\d{2}/", $Day)) {
     2513                if (is_dir(self::$logPath)) {
     2514                    if (file_exists(self::$logPath . "/" . $Day . ".log")) {
     2515                        header("Content-Description: File Transfer");
     2516                        header("Content-Type: application/octet-stream");
     2517                        header("Content-Disposition: attachment; filename=" . $Day . ".log");
     2518                        readfile(self::$logPath . "/" . $Day . ".log");
     2519                        exit;
    24242520                    } else {
    24252521                        $response['Status'] = 'Failed';
    2426                         $response['Message'] = 'Couldn\'t read the log - directory';
     2522                        $response['Message'] = 'Log file for: ' . $Day . ' not found';
    24272523                        exit(json_encode($response));
    24282524                    }
    24292525                } else {
    24302526                    $response['Status'] = 'Failed';
    2431                     $response['Message'] = 'Expecting the date to be formatted as: YYYY-mm-dd';
     2527                    $response['Message'] = 'Couldn\'t read the log - directory';
    24322528                    exit(json_encode($response));
    24332529                }
    24342530            } else {
    24352531                $response['Status'] = 'Failed';
    2436                 $response['Message'] = 'No date specified';
     2532                $response['Message'] = 'Expecting the date to be formatted as: YYYY-mm-dd';
    24372533                exit(json_encode($response));
    24382534            }
    2439         }
    2440 
    2441         public
    2442         function getAvailableLogs($Limit = 25)
    2443         {
    2444             if ($handle = opendir(self::$logPath)) {
    2445                 $AvailableLogs = array();
    2446                 while (false !== ($entry = readdir($handle))) {
    2447                     if ($entry != "." && $entry != "..") {
    2448                         if (preg_match("/\d{4}-\d{2}-\d{2}/", $entry)) {
    2449                             if (filesize(self::$logPath . "/" . $entry) > 0) {
    2450                                 $AvailableLogs[] = preg_replace("/\.log$/", "", $entry);
    2451                             }
     2535        } else {
     2536            $response['Status'] = 'Failed';
     2537            $response['Message'] = 'No date specified';
     2538            exit(json_encode($response));
     2539        }
     2540    }
     2541
     2542    public
     2543    function getAvailableLogs($Limit = 25)
     2544    {
     2545        if ($handle = opendir(self::$logPath)) {
     2546            $AvailableLogs = array();
     2547            while (false !== ($entry = readdir($handle))) {
     2548                if ($entry != "." && $entry != "..") {
     2549                    if (preg_match("/\d{4}-\d{2}-\d{2}/", $entry)) {
     2550                        if (filesize(self::$logPath . "/" . $entry) > 0) {
     2551                            $AvailableLogs[] = preg_replace("/\.log$/", "", $entry);
    24522552                        }
    24532553                    }
    24542554                }
     2555            }
     2556            $response['Status'] = 'Success';
     2557            $response['Files'] = $AvailableLogs;
     2558        } else {
     2559            $response['Status'] = 'Failed';
     2560            $response['Files'] = array();
     2561        }
     2562        return $response;
     2563    }
     2564
     2565    public
     2566    function readLogs($data)
     2567    {
     2568        $response = array();
     2569        if (isset($data['date'])) {
     2570            $Day = $data['date'];
     2571            if (!preg_match("/\d{4}-\d{2}-\d{2}/", $Day)) {
     2572                $response['Status'] = 'Failed';
     2573                $response['Message'] = 'Expecting the date to be formatted as: YYYY-mm-dd';
     2574                exit(json_encode($response));
     2575            }
     2576        } else {
     2577            $Day = date('Y-m-d');
     2578        }
     2579        if (is_dir(self::$logPath)) {
     2580            if (file_exists(self::$logPath . "/" . $Day . ".log")) {
    24552581                $response['Status'] = 'Success';
    2456                 $response['Files'] = $AvailableLogs;
    2457             } else {
    2458                 $response['Status'] = 'Failed';
    2459                 $response['Files'] = array();
    2460             }
    2461             return $response;
    2462         }
    2463 
    2464         public
    2465         function readLogs($data)
    2466         {
    2467             $response = array();
    2468             if (isset($data['date'])) {
    2469                 $Day = $data['date'];
    2470                 if (!preg_match("/\d{4}-\d{2}-\d{2}/", $Day)) {
    2471                     $response['Status'] = 'Failed';
    2472                     $response['Message'] = 'Expecting the date to be formatted as: YYYY-mm-dd';
    2473                     exit(json_encode($response));
    2474                 }
    2475             } else {
    2476                 $Day = date('Y-m-d');
    2477             }
    2478             if (is_dir(self::$logPath)) {
    2479                 if (file_exists(self::$logPath . "/" . $Day . ".log")) {
    2480                     $response['Status'] = 'Success';
    2481                     $MemoryAvailable = self::returnBytes(ini_get('memory_limit'));
    2482                     $fp = fopen(self::$logPath . "/" . $Day . ".log", 'r');
    2483                     if ($fp !== false) {
    2484                         $lines = array();
    2485                         $currentLine = '';
    2486                         $pos = -2; // Skip final new line character (Set to -1 if not present)
    2487                         while (-1 !== fseek($fp, $pos, SEEK_END) && ($MemoryAvailable - memory_get_usage()) > self::returnBytes("10MB")) {
    2488                             $char = fgetc($fp);
    2489                             if (PHP_EOL == $char) {
    2490                                 $lines[] = $currentLine;
    2491                                 $currentLine = '';
    2492                             } else {
    2493                                 $currentLine = $char . $currentLine;
    2494                             }
    2495                             $pos--;
    2496                         }
    2497 
    2498                         if (($MemoryAvailable - memory_get_usage()) > self::returnBytes("10MB")) {
    2499                             $lines[] = $currentLine; // Grab final line
    2500                         }
    2501                         fclose($fp);
    2502                         $response['Logs'] = $lines;
    2503                     } else {
    2504                         $response['Status'] = 'Failed';
    2505                         $response['Logs'] = array(
    2506                             "Failed to open log-file for: " . $Day
    2507                         );
    2508                     }
     2582                $MemoryAvailable = self::returnBytes(ini_get('memory_limit'));
     2583                $fp = fopen(self::$logPath . "/" . $Day . ".log", 'r');
     2584                if ($fp !== false) {
     2585                    $lines = array();
     2586                    $currentLine = '';
     2587                    $pos = -2; // Skip final new line character (Set to -1 if not present)
     2588                    while (-1 !== fseek($fp, $pos, SEEK_END) && ($MemoryAvailable - memory_get_usage()) > self::returnBytes("10MB")) {
     2589                        $char = fgetc($fp);
     2590                        if (PHP_EOL == $char) {
     2591                            $lines[] = $currentLine;
     2592                            $currentLine = '';
     2593                        } else {
     2594                            $currentLine = $char . $currentLine;
     2595                        }
     2596                        $pos--;
     2597                    }
     2598
     2599                    if (($MemoryAvailable - memory_get_usage()) > self::returnBytes("10MB")) {
     2600                        $lines[] = $currentLine; // Grab final line
     2601                    }
     2602                    fclose($fp);
     2603                    $response['Logs'] = $lines;
    25092604                } else {
    25102605                    $response['Status'] = 'Failed';
    25112606                    $response['Logs'] = array(
    2512                         "No logs found for: " . $Day
     2607                        "Failed to open log-file for: " . $Day
    25132608                    );
    25142609                }
     
    25162611                $response['Status'] = 'Failed';
    25172612                $response['Logs'] = array(
    2518                     "Failed to read logs for: " . $Day
     2613                    "No logs found for: " . $Day
    25192614                );
    25202615            }
    2521             return $response;
    2522         }
    2523 
    2524         public
    2525         function getProduct($request)
    2526         {
    2527 
    2528             global $woocommerce;
    2529 
    2530             header('Access-Control-Allow-Origin: *');
    2531             header("Access-Control-Allow-Methods: GET");
    2532 
    2533             if (class_exists('WooCommerce')) {
    2534 
    2535                 $token = $request->get_param('token');
    2536                 $searchterm = $request->get_param('searchterm');
    2537 
    2538                 if (isset($token)) {
    2539 
    2540                     $currency_symbol = get_woocommerce_currency_symbol();
    2541                     $currency_symbol = html_entity_decode($currency_symbol);
    2542 
    2543                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    2544                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    2545 
    2546                         // Search by sku
     2616        } else {
     2617            $response['Status'] = 'Failed';
     2618            $response['Logs'] = array(
     2619                "Failed to read logs for: " . $Day
     2620            );
     2621        }
     2622        return $response;
     2623    }
     2624
     2625    public
     2626    function getProduct($request)
     2627    {
     2628
     2629        global $woocommerce;
     2630
     2631        header('Access-Control-Allow-Origin: *');
     2632        header("Access-Control-Allow-Methods: GET");
     2633
     2634        if (class_exists('WooCommerce')) {
     2635
     2636            $token = $request->get_param('token');
     2637            $searchterm = $request->get_param('searchterm');
     2638
     2639            if (isset($token)) {
     2640
     2641                $currency_symbol = get_woocommerce_currency_symbol();
     2642                $currency_symbol = html_entity_decode($currency_symbol);
     2643
     2644                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     2645                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     2646
     2647                    // Search by sku
     2648                    $args = array(
     2649                        'post_type' => array('product', 'product_variation'),
     2650                        'post_status' => 'any',
     2651                        'posts_per_page' => -1,
     2652                        'meta_query' => array(
     2653                            'relation' => 'OR',
     2654                            array(
     2655                                'key' => '_sku',
     2656                                'value' => $searchterm
     2657                            ),
     2658                        ),
     2659                        'fields' => 'ids'
     2660                    );
     2661
     2662                    // Search by custom EAN field
     2663                    $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
     2664                    if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
     2665                        $args['meta_query'][] = array(
     2666                            'key' => $orderpickingapp_ean_field,
     2667                            'value' => $searchterm
     2668                        );
     2669                    }
     2670                    $product_query = new WP_Query($args);
     2671                    $product_ids = $product_query->posts;
     2672
     2673                    // Search by product/variation id
     2674                    if (empty($product_ids)) {
    25472675                        $args = array(
    25482676                            'post_type' => array('product', 'product_variation'),
    25492677                            'post_status' => 'any',
    2550                             'posts_per_page' => -1,
    2551                             'meta_query' => array(
    2552                                 'relation' => 'OR',
    2553                                 array(
    2554                                     'key' => '_sku',
    2555                                     'value' => $searchterm
    2556                                 ),
    2557                             ),
     2678                            'posts_per_page' => 1,
     2679                            'post__in' => (array)$searchterm,
    25582680                            'fields' => 'ids'
    25592681                        );
    2560 
    2561                         // Search by custom EAN field
    2562                         $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
    2563                         if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
    2564                             $args['meta_query'][] = array(
    2565                                 'key' => $orderpickingapp_ean_field,
    2566                                 'value' => $searchterm
    2567                             );
    2568                         }
    25692682                        $product_query = new WP_Query($args);
    25702683                        $product_ids = $product_query->posts;
    2571 
    2572                         // Search by product/variation id
    2573                         if (empty($product_ids)) {
    2574                             $args = array(
    2575                                 'post_type' => array('product', 'product_variation'),
    2576                                 'post_status' => 'any',
    2577                                 'posts_per_page' => 1,
    2578                                 'post__in' => (array)$searchterm,
    2579                                 'fields' => 'ids'
     2684                    }
     2685
     2686                    // Search by title
     2687                    if (empty($product_ids)) {
     2688                        $args = array(
     2689                            's' => $searchterm,
     2690                            'post_type' => array('product'),
     2691                            'post_status' => 'any',
     2692                            'posts_per_page' => -1,
     2693                            'fields' => 'ids'
     2694                        );
     2695                        $product_query = new WP_Query($args);
     2696                        $product_ids = $product_query->posts;
     2697                    }
     2698
     2699                    $Products = array();
     2700                    if (isset($product_ids[0])) {
     2701                        foreach ($product_ids as $product_id) {
     2702
     2703                            $product_info = wc_get_product($product_id);
     2704                            $product_details = $product_info->get_data();
     2705
     2706                            $title = $product_info->get_name();
     2707
     2708                            $main_product_id = $product_id;
     2709                            if ($product_info->get_parent_id() !== 0) {
     2710                                $main_product_id = $product_info->get_parent_id();
     2711                            }
     2712
     2713                            // YOAST COMPATIBILITY
     2714                            $primary_product_cat = get_post_meta($main_product_id, '_yoast_wpseo_primary_product_cat', true);
     2715                            if (isset($primary_product_cat) && !empty($primary_product_cat)) {
     2716                                $primary_term = get_term($primary_product_cat);
     2717
     2718                                if (!empty($primary_term->parent)) {
     2719                                    $categories[] = get_term($primary_term->parent)->name;
     2720                                }
     2721
     2722                                $categories[] = get_term($primary_product_cat)->name;
     2723                            } else {
     2724                                $categories = wp_get_post_terms($main_product_id, 'product_cat', array("orderby" => "parent"));
     2725
     2726                                if (isset($categories) && !empty($categories)) {
     2727                                    $categories = wp_list_pluck($categories, 'name');
     2728                                } else {
     2729                                    $categories = array();
     2730                                }
     2731                            }
     2732
     2733                            $categoryHierarchy = array();
     2734                            $this->productCategories = array();
     2735                            $product_categories = get_the_terms($main_product_id, 'product_cat', array('hide_empty' => false));
     2736
     2737                            if (isset($product_categories) && is_array($product_categories)) {
     2738                                $this->sort_terms_hierarchically($product_categories, $categoryHierarchy);
     2739                            }
     2740
     2741                            $order_cat_id = end($this->productCategories);
     2742                            if (count($this->productCategories) > 2) {
     2743                                $order_cat_id = $this->productCategories[1];
     2744                            }
     2745
     2746                            $thumbnail = get_the_post_thumbnail_url($main_product_id, 'medium');
     2747
     2748                            $sku = $product_details['sku'];
     2749
     2750                            if (empty($sku)) {
     2751                                $sku = $product_id;
     2752                                $barcode = 'no sku / barcode';
     2753                            } else {
     2754                                $barcode = $sku;
     2755                            }
     2756
     2757                            if (!empty($product_details['short_description'])) {
     2758                                $description = $product_details['short_description'];
     2759                            } else {
     2760                                $description = $product_details['description'];
     2761                            }
     2762
     2763                            $price = $product_info->get_price();
     2764                            if (isset($price) && !empty($price)) {
     2765                                $price = $currency_symbol . ' ' . number_format($product_info->get_price(), 2, ",", ".");
     2766                            } else {
     2767                                $price = '-';
     2768                            }
     2769
     2770                            $stock = $product_info->get_stock_quantity();
     2771                            if ($stock == NULL && !$product_info->managing_stock()) {
     2772                                $stock_status = $product_info->get_stock_status();
     2773
     2774                                if ($stock_status == 'outofstock') {
     2775                                    $stock = 'OUT_OF_STOCK';
     2776                                } elseif ($stock_status == 'onbackorder') {
     2777                                    $stock = 'ON_BACKORDER';
     2778                                } else {
     2779                                    $stock = 'IN_STOCK';
     2780                                }
     2781                            }
     2782
     2783                            $description = strip_tags($description, '<p><a><strong><i>');
     2784                            $description = str_replace(array("\r", "\n"), '', $description);
     2785                            if (strlen($description) > 200) {
     2786                                $description = substr($description, 0, 200) . '...';
     2787                            }
     2788
     2789                            if (!empty($meta_description)) {
     2790                                $description = $meta_description;
     2791                            }
     2792
     2793                            if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
     2794                                $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
     2795                            }
     2796
     2797                            if (strpos($thumbnail, "?")) {
     2798                                $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
     2799                            }
     2800                            if (!isset($thumbnail) || empty($thumbnail)) {
     2801                                $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
     2802                            }
     2803
     2804                            $product_data = array(
     2805                                'product_id' => $product_id,
     2806                                'title' => $title,
     2807                                'thumbnail' => $thumbnail,
     2808                                'description' => $description,
     2809                                'sku' => $sku,
     2810                                'barcode' => $barcode,
     2811                                'price' => $price,
     2812                                'stock' => $stock,
     2813                                'order_cat' => $order_cat_id,
     2814                                'categories' => implode(' / ', $categories),
    25802815                            );
    2581                             $product_query = new WP_Query($args);
    2582                             $product_ids = $product_query->posts;
    2583                         }
    2584 
    2585                         // Search by title
    2586                         if (empty($product_ids)) {
    2587                             $args = array(
    2588                                 's' => $searchterm,
    2589                                 'post_type' => array('product'),
    2590                                 'post_status' => 'any',
    2591                                 'posts_per_page' => -1,
    2592                                 'fields' => 'ids'
    2593                             );
    2594                             $product_query = new WP_Query($args);
    2595                             $product_ids = $product_query->posts;
    2596                         }
    2597 
    2598                         $Products = array();
    2599                         if (isset($product_ids[0])) {
    2600                             foreach ($product_ids as $product_id) {
    2601 
    2602                                 $product_info = wc_get_product($product_id);
    2603                                 $product_details = $product_info->get_data();
    2604 
    2605                                 $title = $product_info->get_name();
    2606 
    2607                                 $main_product_id = $product_id;
    2608                                 if ($product_info->get_parent_id() !== 0) {
    2609                                     $main_product_id = $product_info->get_parent_id();
    2610                                 }
    2611 
    2612                                 // YOAST COMPATIBILITY
    2613                                 $primary_product_cat = get_post_meta($main_product_id, '_yoast_wpseo_primary_product_cat', true);
    2614                                 if (isset($primary_product_cat) && !empty($primary_product_cat)) {
    2615                                     $primary_term = get_term($primary_product_cat);
    2616 
    2617                                     if (!empty($primary_term->parent)) {
    2618                                         $categories[] = get_term($primary_term->parent)->name;
    2619                                     }
    2620 
    2621                                     $categories[] = get_term($primary_product_cat)->name;
    2622                                 } else {
    2623                                     $categories = wp_get_post_terms($main_product_id, 'product_cat', array("orderby" => "parent"));
    2624 
    2625                                     if (isset($categories) && !empty($categories)) {
    2626                                         $categories = wp_list_pluck($categories, 'name');
    2627                                     } else {
    2628                                         $categories = array();
    2629                                     }
    2630                                 }
    2631 
    2632                                 $categoryHierarchy = array();
    2633                                 $this->productCategories = array();
    2634                                 $product_categories = get_the_terms($main_product_id, 'product_cat', array('hide_empty' => false));
    2635 
    2636                                 if (isset($product_categories) && is_array($product_categories)) {
    2637                                     $this->sort_terms_hierarchically($product_categories, $categoryHierarchy);
    2638                                 }
    2639 
    2640                                 $order_cat_id = end($this->productCategories);
    2641                                 if (count($this->productCategories) > 2) {
    2642                                     $order_cat_id = $this->productCategories[1];
    2643                                 }
    2644 
    2645                                 $thumbnail = get_the_post_thumbnail_url($main_product_id, 'medium');
    2646 
    2647                                 $sku = $product_details['sku'];
    2648 
    2649                                 if (empty($sku)) {
    2650                                     $sku = $product_id;
    2651                                     $barcode = 'no sku / barcode';
    2652                                 } else {
    2653                                     $barcode = $sku;
    2654                                 }
    2655 
    2656                                 if (!empty($product_details['short_description'])) {
    2657                                     $description = $product_details['short_description'];
    2658                                 } else {
    2659                                     $description = $product_details['description'];
    2660                                 }
    2661 
    2662                                 $price = $product_info->get_price();
    2663                                 if (isset($price) && !empty($price)) {
    2664                                     $price = $currency_symbol . ' ' . number_format($product_info->get_price(), 2, ",", ".");
    2665                                 } else {
    2666                                     $price = '-';
    2667                                 }
    2668 
    2669                                 $stock = $product_info->get_stock_quantity();
    2670                                 if ($stock == NULL && !$product_info->managing_stock()) {
    2671                                     $stock_status = $product_info->get_stock_status();
    2672 
    2673                                     if ($stock_status == 'outofstock') {
    2674                                         $stock = 'OUT_OF_STOCK';
    2675                                     } elseif ($stock_status == 'onbackorder') {
    2676                                         $stock = 'ON_BACKORDER';
    2677                                     } else {
    2678                                         $stock = 'IN_STOCK';
    2679                                     }
    2680                                 }
    2681 
    2682                                 $description = strip_tags($description, '<p><a><strong><i>');
    2683                                 $description = str_replace(array("\r", "\n"), '', $description);
    2684                                 if (strlen($description) > 200) {
    2685                                     $description = substr($description, 0, 200) . '...';
    2686                                 }
    2687 
    2688                                 if (!empty($meta_description)) {
    2689                                     $description = $meta_description;
    2690                                 }
    2691 
    2692                                 if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
    2693                                     $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
    2694                                 }
    2695 
    2696                                 if (strpos($thumbnail, "?")) {
    2697                                     $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
    2698                                 }
    2699                                 if (!isset($thumbnail) || empty($thumbnail)) {
    2700                                     $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
    2701                                 }
    2702 
    2703                                 $product_data = array(
    2704                                     'product_id' => $product_id,
    2705                                     'title' => $title,
    2706                                     'thumbnail' => $thumbnail,
    2707                                     'description' => $description,
    2708                                     'sku' => $sku,
    2709                                     'barcode' => $barcode,
    2710                                     'price' => $price,
    2711                                     'stock' => $stock,
    2712                                     'order_cat' => $order_cat_id,
    2713                                     'categories' => implode(' / ', $categories),
    2714                                 );
    2715 
    2716                                 $Products[] = $product_data;
    2717                             }
    2718 
    2719                             wp_send_json($Products);
    2720                         } else {
    2721                             $args = array(
    2722                                 'status' => 400,
    2723                                 'message' => 'Product with his searchterm nog found!',
    2724                             );
    2725                             wp_send_json($args);
    2726                         }
     2816
     2817                            $Products[] = $product_data;
     2818                        }
     2819
     2820                        wp_send_json($Products);
    27272821                    } else {
    2728                         header("HTTP/1.1 401 Unauthorized");
    2729                         exit;
     2822                        $args = array(
     2823                            'status' => 400,
     2824                            'message' => 'Product with his searchterm nog found!',
     2825                        );
     2826                        wp_send_json($args);
    27302827                    }
    27312828                } else {
     
    27332830                    exit;
    27342831                }
     2832            } else {
     2833                header("HTTP/1.1 401 Unauthorized");
     2834                exit;
    27352835            }
    27362836        }
    2737 
    2738         public
    2739         function updateProduct($request)
    2740         {
    2741 
    2742             header('Access-Control-Allow-Origin: *');
    2743             header("Access-Control-Allow-Credentials: true");
    2744             header('Access-Control-Allow-Methods: POST');
    2745             header('Access-Control-Max-Age: 1000');
    2746             header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');
    2747 
    2748             if (class_exists('WooCommerce')) {
    2749 
    2750                 $token = $request->get_param('token');
    2751                 $product_id = $request->get_param('productid');
    2752                 $stock = $request->get_param('stock');
    2753                 if (isset($token)) {
    2754 
    2755                     $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
    2756                     if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
    2757                         $product = wc_get_product($product_id);
    2758                         $product->set_stock_quantity($stock);
    2759                         $product->save();
    2760                     }
    2761                 } else {
    2762                     header("HTTP/1.1 401 Unauthorized");
    2763                     exit;
     2837    }
     2838
     2839    public
     2840    function updateProduct($request)
     2841    {
     2842
     2843        header('Access-Control-Allow-Origin: *');
     2844        header("Access-Control-Allow-Credentials: true");
     2845        header('Access-Control-Allow-Methods: POST');
     2846        header('Access-Control-Max-Age: 1000');
     2847        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');
     2848
     2849        if (class_exists('WooCommerce')) {
     2850
     2851            $token = $request->get_param('token');
     2852            $product_id = $request->get_param('productid');
     2853            $stock = $request->get_param('stock');
     2854            if (isset($token)) {
     2855
     2856                $orderpickingapp_apikey = get_option('orderpickingapp_apikey');
     2857                if (isset($orderpickingapp_apikey) && $token == $orderpickingapp_apikey) {
     2858                    $product = wc_get_product($product_id);
     2859                    $product->set_stock_quantity($stock);
     2860                    $product->save();
    27642861                }
     2862            } else {
     2863                header("HTTP/1.1 401 Unauthorized");
     2864                exit;
    27652865            }
    2766             exit;
    2767         }
    2768 
    2769         function returnBytes($val)
    2770         {
    2771             $val = trim($val);
    2772             $last = strtolower($val[strlen($val) - 1]);
    2773             $val = substr($val, 0, strlen($val) - 1);
    2774             switch ($last) {
    2775                 case 'g':
    2776                     $val *= 1024;
    2777                 case 'm':
    2778                     $val *= 1024;
    2779                 case 'k':
    2780                     $val *= 1024;
    2781             }
    2782             return $val;
    2783         }
    2784 
     2866        }
     2867        exit;
    27852868    }
     2869
     2870    function returnBytes($val)
     2871    {
     2872        $val = trim($val);
     2873        $last = strtolower($val[strlen($val) - 1]);
     2874        $val = substr($val, 0, strlen($val) - 1);
     2875        switch ($last) {
     2876            case 'g':
     2877                $val *= 1024;
     2878            case 'm':
     2879                $val *= 1024;
     2880            case 'k':
     2881                $val *= 1024;
     2882        }
     2883        return $val;
     2884    }
     2885
     2886}
  • order-picking-app/trunk/orderpickingapp.php

    r3172741 r3185485  
    33 * Plugin Name:       Order Picking App
    44 * Description:       Make your life easier by using the Orderpicking App. You'll never be inefficient if the Orderpicking App is installed in your store. We assist you in all aspects of your webshop. From intelligent selecting to order packing, we have you covered. Connecting the Orderpicking App to your Woocommerce webshop is simple and quick. Within an hour, you'll be online with the Orderpicking App. You're able to pick and pack your orders three times faster and with greater accuracy.
    5  * Version:           1.6.7
     5 * Version:           1.6.8
    66 * Author:            Arture | PHP Professionals
    77 * Author URI:        http://arture.nl
  • order-picking-app/trunk/readme.txt

    r3172741 r3185485  
    55Requires at least: 6.0
    66Tested up to: 6.6.2
    7 Stable tag: 1.6.7
     7Stable tag: 1.6.8
    88Requires PHP: 7.4
    99License: GPLv2 or later
     
    3737== Changelog ==
    3838
     39= 1.6.8 =
     40* NEW | Order functions for scan and collect products and creating orders
     41
    3942= 1.6.7 =
    4043* NEW | Desktop packing page
Note: See TracChangeset for help on using the changeset viewer.