public function checkProductInventory($mode = 'published', $compare_prices = false)
 {
     // get all published listings
     $lm = new WPLA_ListingsModel();
     $listings = $mode == 'published' ? $lm->getWhere('status', 'online') : $lm->getWhere('status', 'sold');
     $out_of_sync_products = array();
     $published_count = 0;
     // echo "<pre>";print_r($listings);echo"</pre>";#die();
     // process published listings
     foreach ($listings as $item) {
         // check wc product
         $item = (array) $item;
         $post_id = $item['post_id'];
         $_product = $this->getProduct($post_id);
         // echo "<pre>";print_r($_product);echo"</pre>";die();
         // checking parent variations makes no sense in WPLA, so skip them
         if ($_product->product_type == 'variable') {
             continue;
         }
         // get stock level and price
         $stock = WPLA_ProductWrapper::getStock($item['post_id']);
         $price = WPLA_ProductWrapper::getPrice($item['post_id']);
         // $item['price_max'] = $price;
         // echo "<pre>";print_r($price);echo"</pre>";#die();
         // echo "<pre>";print_r($item);echo"</pre>";die();
         // check for sale price on amazon side
         $sale_price = $this->getSalePriceForItem($item);
         $amazon_price = $sale_price ? $sale_price : $item['price'];
         // check if product and amazon listing are in sync
         $in_sync = true;
         // check stock level
         if ($stock != $item['quantity']) {
             $in_sync = false;
         }
         // check price
         if ($compare_prices) {
             if (round($price, 2) != round($amazon_price, 2)) {
                 $in_sync = false;
             }
         }
         // check max price
         // if ( isset( $price_max ) && isset( $item['price_max'] ) && ( round( $price_max, 2 ) != round ( $item['price_max'], 2 ) ) )
         // 	$in_sync = false;
         // if in sync, continue with next item
         if ($in_sync) {
             continue;
         }
         // mark listing as changed
         if (isset($_REQUEST['mark_as_changed'])) {
             if ($_product) {
                 // only existing products can have a profile re-applied
                 $lm->markItemAsModified($item['post_id']);
             }
             // in case the product is missing, force the listing to be changed (?)
             $lm->updateListing($item['id'], array('status' => 'changed'));
             $item['status'] = 'changed';
         }
         // add to list of out of sync products
         $item['price_woo'] = $price;
         $item['price_woo_max'] = isset($price_max) ? $price_max : false;
         $item['stock'] = $stock;
         $item['exists'] = $_product ? true : false;
         $item['type'] = $_product ? $_product->product_type : 'missing';
         $item['parent_id'] = $_product->product_type == 'variation' ? $_product->parent->id : false;
         $out_of_sync_products[] = $item;
         // count products which have not yet been marked as changed
         if ($item['status'] == 'online') {
             $published_count += 1;
         }
     }
     // return if empty
     if (empty($out_of_sync_products)) {
         WPLA()->showMessage('All ' . $mode . ' listings seem to be in sync.', 0, 1);
         return;
     }
     $msg = '<p>';
     $msg .= 'Warning: ' . sizeof($out_of_sync_products) . ' ' . $mode . ' listings are out of sync or missing in WooCommerce.';
     $msg .= '</p>';
     // table header
     $msg .= '<table style="width:100%">';
     $msg .= "<tr>";
     $msg .= "<th style='text-align:left'>SKU</th>";
     $msg .= "<th style='text-align:left'>Product</th>";
     $msg .= "<th style='text-align:left'>Local Qty</th>";
     $msg .= "<th style='text-align:left'>Amazon Qty</th>";
     $msg .= "<th style='text-align:left'>Local Price</th>";
     $msg .= "<th style='text-align:left'>Amazon Price</th>";
     $msg .= "<th style='text-align:left'>ASIN</th>";
     $msg .= "<th style='text-align:left'>Status</th>";
     $msg .= "</tr>";
     // table rows
     foreach ($out_of_sync_products as $item) {
         // echo "<pre>";print_r($item['asin']);echo"</pre>";#die();
         // get column data
         $sku = $item['sku'];
         $qty = $item['quantity'];
         $stock = $item['stock'];
         $title = $item['listing_title'];
         $post_id = $item['post_id'];
         $asin = $item['asin'];
         $status = $item['status'];
         $exists = $item['exists'];
         $price = woocommerce_price($item['price']);
         $price_woo = woocommerce_price($item['price_woo']);
         $product_type = $item['type'] == 'simple' ? '' : $item['type'];
         // highlight changed values
         $changed_stock = intval($item['quantity']) == intval($item['stock']) ? false : true;
         $changed_price = floatval($item['price']) == floatval($item['price_woo']) ? false : true;
         $changed_price_max = floatval(@$item['price_max']) == floatval($item['price_woo_max']) ? false : true;
         $stock_css = $changed_stock ? 'color:darkred;' : '';
         $price_css = $changed_price || $changed_price_max ? 'color:darkred;' : '';
         if (!$compare_prices) {
             $price_css = '';
         }
         // build links
         // $amazon_url  = $item['ViewItemURL'] ? $item['ViewItemURL'] : $amazon_url = 'http://www.amazon.com/itm/'.$asin;
         $amazon_url = 'admin.php?page=wpla&s=' . $asin;
         $amazon_link = '<a href="' . $amazon_url . '" target="_blank">' . $asin . '</a>';
         $edit_link = '<a href="post.php?action=edit&post=' . ($item['parent_id'] ? $item['parent_id'] : $post_id) . '" target="_blank">' . $title . '</a>';
         // mark non existent products
         if (!$exists) {
             $stock = 'N/A';
             $post_id .= ' missing!';
         }
         // show price range for variations
         // if ( $item['price_woo_max'] )
         // 	$price_woo .= ' - '.woocommerce_price( $item['price_woo_max'] );
         // if ( @$item['price_max'] )
         // 	$price .= ' - '.woocommerce_price( $item['price_max'] );
         // build table row
         $msg .= "<tr>";
         $msg .= "<td>{$sku}</td>";
         $msg .= "<td>{$edit_link} <span style='color:silver'>{$product_type} (#{$post_id})</span></td>";
         $msg .= "<td style='{$stock_css}'>{$stock}</td>";
         $msg .= "<td style='{$stock_css}'>{$qty}</td>";
         $msg .= "<td style='{$price_css}'>{$price_woo}</td>";
         $msg .= "<td style='{$price_css}'>{$price}</td>";
         $msg .= "<td>{$amazon_link}</td>";
         $msg .= "<td>{$status}</td>";
         $msg .= "</tr>";
     }
     $msg .= '</table>';
     // buttons
     $msg .= '<p>';
     // show 'check again' button
     $url = 'admin.php?page=wpla-tools&tab=inventory&action=check_wc_out_of_sync&mode=' . $mode . '&prices=' . $compare_prices . '&_wpnonce=' . wp_create_nonce('wpla_tools_page');
     $msg .= '<a href="' . $url . '" class="button">' . __('Check again', 'wpla') . '</a> &nbsp; ';
     // show 'mark all as changed' button
     if ($mode == 'published') {
         if ($published_count) {
             $url = 'admin.php?page=wpla-tools&tab=inventory&action=check_wc_out_of_sync&mark_as_changed=yes&mode=' . $mode . '&prices=' . $compare_prices . '&_wpnonce=' . wp_create_nonce('wpla_tools_page');
             $msg .= '<a href="' . $url . '" class="button">' . __('Mark all as changed', 'wpla') . '</a> &nbsp; ';
             $msg .= 'Click this button to mark all found listings as changed in WP-Lister.';
         } else {
             // $msg .= '<a id="btn_revise_all_changed_items_reminder" class="btn_revise_all_changed_items_reminder button wpl_job_button">' . __('Revise all changed items','wpla') . '</a>';
             // $msg .= ' &nbsp; ';
             // $msg .= 'Click to revise all changed items.';
         }
     }
     $msg .= '</p>';
     WPLA()->showMessage($msg, 1, 1);
 }
 public static function updateMinMaxPrices($item_ids)
 {
     // echo "<pre>";print_r($item_ids);echo"</pre>";
     // TODO: sanitize values
     $min_base_price = trim($_REQUEST['min_base_price']);
     $min_price_percentage = trim($_REQUEST['min_price_percentage']);
     $min_price_amount = trim($_REQUEST['min_price_amount']);
     $max_base_price = trim($_REQUEST['max_base_price']);
     $max_price_percentage = trim($_REQUEST['max_price_percentage']);
     $max_price_amount = trim($_REQUEST['max_price_amount']);
     $min_price_amount = str_replace(',', '.', $min_price_amount);
     // convert decimal comma
     $max_price_amount = str_replace(',', '.', $max_price_amount);
     // remember last used options
     $options = array('min_base_price' => $min_base_price, 'max_base_price' => $max_base_price, 'min_price_amount' => $min_price_amount, 'max_price_amount' => $max_price_amount, 'min_price_percentage' => $min_price_percentage, 'max_price_percentage' => $max_price_percentage);
     update_option('wpla_price_wizard_options', $options);
     $lm = new WPLA_ListingsModel();
     foreach ($item_ids as $listing_id) {
         // load listing item
         $item = $lm->getItem($listing_id, OBJECT);
         if (!$item) {
             continue;
         }
         if ($item->product_type == 'variable') {
             continue;
         }
         $post_id = $item->post_id;
         // get base price (min)
         $base_price = 0;
         if ($min_base_price == 'price') {
             $base_price = WPLA_ProductWrapper::getPrice($post_id);
         }
         if ($min_base_price == 'sale_price') {
             $base_price = WPLA_ProductWrapper::getSalePrice($post_id);
         }
         if ($min_base_price == 'msrp') {
             $base_price = get_post_meta($post_id, '_msrp', true) ? get_post_meta($post_id, '_msrp', true) : get_post_meta($post_id, '_msrp_price', true);
         }
         // calculate new min price
         if ($min_price_percentage) {
             $base_price = $base_price + $base_price * floatval($min_price_percentage) / 100;
         }
         if ($min_price_amount) {
             $base_price = $base_price + floatval($min_price_amount);
         }
         if ($min_base_price == 'no_change') {
             $base_price = $item->min_price;
         }
         $new_min_price = round($base_price, 2);
         // get base price (max)
         $base_price = 0;
         if ($max_base_price == 'price') {
             $base_price = WPLA_ProductWrapper::getPrice($post_id);
         }
         if ($max_base_price == 'sale_price') {
             $base_price = WPLA_ProductWrapper::getSalePrice($post_id);
         }
         if ($max_base_price == 'msrp') {
             $base_price = get_post_meta($post_id, '_msrp', true) ? get_post_meta($post_id, '_msrp', true) : get_post_meta($post_id, '_msrp_price', true);
         }
         // calculate new max price
         if ($max_price_percentage) {
             $base_price = $base_price + $base_price * floatval($max_price_percentage) / 100;
         }
         if ($max_price_amount) {
             $base_price = $base_price + floatval($max_price_amount);
         }
         if ($max_base_price == 'no_change') {
             $base_price = $item->max_price;
         }
         $new_max_price = round($base_price, 2);
         // update listing table
         $data = array('min_price' => $new_min_price, 'max_price' => $new_max_price, 'pnq_status' => 1);
         $lm->updateWhere(array('id' => $listing_id), $data);
         // update product
         update_post_meta($item->post_id, '_amazon_minimum_price', $new_min_price);
         update_post_meta($item->post_id, '_amazon_maximum_price', $new_max_price);
     }
     // foreach item
 }
 public function applyProfileToItem($profile, $item)
 {
     global $wpdb;
     // allow to pass a listing_id instead of item object
     if (!is_object($item)) {
         $item = $this->getItem($item, OBJECT);
     }
     // echo "<pre>";print_r($item);echo"</pre>";#die();
     // get item data
     $id = $item->id;
     $post_id = $item->post_id;
     $status = $item->status;
     $asin = $item->asin;
     // gather profile data
     $data = array();
     $data['profile_id'] = $profile->id;
     $data['account_id'] = $profile->account_id;
     // apply profile price
     $data['price'] = WPLA_ProductWrapper::getPrice($post_id);
     $data['price'] = $profile->processProfilePrice($data['price']);
     // update vtheme for child and parent variations
     if (in_array($item->product_type, array('variation', 'variable'))) {
         // $data['vtheme'] == $item->vtheme; ? // check for actual change
         // check profile for variation_theme
         $profile_fields = maybe_unserialize($profile->fields);
         if (is_array($profile_fields) && isset($profile_fields['variation_theme']) && !empty($profile_fields['variation_theme'])) {
             // use variation theme from profile
             $data['vtheme'] = $profile_fields['variation_theme'];
         } else {
             // update variation theme from product (parent variation)
             $parent_id = $item->parent_id ? $item->parent_id : $item->post_id;
             $data['vtheme'] = self::getVariationThemeForPostID($parent_id);
         }
     }
     // if variable product
     // default new status is 'changed'
     $data['status'] = 'changed';
     if ($status == 'failed') {
         $data['status'] = 'changed';
     }
     if ($status == 'online') {
         $data['status'] = 'changed';
     }
     // except for matched or imported products
     if ($status == 'matched') {
         $data['status'] = $status;
     }
     if ($status == 'imported') {
         $data['status'] = $status;
     }
     if ($status == 'prepared') {
         $data['status'] = $status;
     }
     // submitted items stay 'submitted' and archived items stay archived
     if ($status == 'submitted') {
         $data['status'] = $status;
     }
     if ($status == 'archived') {
         $data['status'] = $status;
     }
     if ($status == 'trash') {
         $data['status'] = $status;
     }
     if ($status == 'trashed') {
         $data['status'] = $status;
     }
     // debug
     if ($status != $data['status']) {
         WPLA()->logger->info('applyProfileToItem(' . $id . ') old status: ' . $status);
         WPLA()->logger->info('applyProfileToItem(' . $id . ') new status: ' . $data['status']);
     }
     // update auctions table
     $wpdb->update($this->tablename, $data, array('id' => $id));
     // WPLA()->logger->info('updating listing ID '.$id);
     // WPLA()->logger->info('data: '.print_r($data,1));
     // WPLA()->logger->info('sql: '.$wpdb->last_query);
     // WPLA()->logger->info('error: '.$wpdb->last_error);
 }