public function action_update_pricing_info()
 {
     WPLA()->logger->info("do_action: wpla_update_pricing_info");
     $accounts = WPLA_AmazonAccount::getAll();
     // $listingsModel = new WPLA_ListingsModel();
     $batch_size = 200;
     // 10 requests per batch (for now - maximum should be 20 requests = 400 items / max. 600 items per minute)
     foreach ($accounts as $account) {
         $account_id = $account->id;
         $listings = WPLA_ListingQueryHelper::getItemsDueForPricingUpdateForAcccount($account_id, $batch_size);
         $listing_ASINs = array();
         WPLA()->logger->info(sprintf('%s items with outdated pricing info found for account %s.', sizeof($listings), $account->title));
         // build array of ASINs
         foreach ($listings as $listing) {
             // skip duplicate ASINs - they throw an error from Amazon
             if (in_array($listing->asin, $listing_ASINs)) {
                 continue;
             }
             $listing_ASINs[] = $listing->asin;
         }
         if (empty($listing_ASINs)) {
             continue;
         }
         // process batches of 20 ASINs
         for ($page = 0; $page < 10; $page++) {
             $page_size = 20;
             // splice ASINs
             $offset = $page * $page_size;
             $ASINs_for_this_batch = array_slice($listing_ASINs, $offset, $page_size);
             if (empty($ASINs_for_this_batch)) {
                 continue;
             }
             // run update
             $this->update_pricing_info_for_asins($ASINs_for_this_batch, $account_id);
             WPLA()->logger->info(sprintf('%s ASINs had their pricing info updated - account %s.', sizeof($listing_ASINs), $account->title));
         }
     }
     // each account
 }
 public function findMissingProducts()
 {
     $items = WPLA_ListingQueryHelper::findMissingProducts();
     $mode = isset($_REQUEST['mode']) ? $_REQUEST['mode'] : false;
     if ($mode == 'delete') {
         foreach ($items as $item) {
             WPLA_ListingsModel::deleteItem($item->id);
         }
         wpla_show_message(sizeof($items) . ' items have been deleted.');
         return;
     }
     if ($mode == 'import') {
         foreach ($items as $item) {
             $data = array('status' => 'imported');
             WPLA_ListingsModel::updateWhere(array('id' => $item->id), $data);
         }
         wpla_show_message(sizeof($items) . ' items have been added to the import queue.');
         return;
     }
     if (!empty($items)) {
         $nonce = wp_create_nonce('wpla_tools_page');
         $btn_delete = '<a href="admin.php?page=wpla-tools&tab=inventory&action=wpla_check_for_missing_products&mode=delete&_wpnonce=' . $nonce . '" class="button button-small button-secondary">' . 'Delete all from DB' . '</a> &nbsp; ';
         $btn_import = '<a href="admin.php?page=wpla-tools&tab=inventory&action=wpla_check_for_missing_products&mode=import&_wpnonce=' . $nonce . '" class="button button-small button-primary"  >' . 'Add to import queue' . '</a>';
         $buttons = ' &nbsp; ' . $btn_delete . $btn_import;
         wpla_show_message('There are ' . sizeof($items) . ' listing(s) without a linked product in WooCommerce.' . $buttons, 'error');
     } else {
         wpla_show_message('No missing products found.');
     }
 }
 public static function adjustLowestPriceForProducts($items = false, $verbose = false)
 {
     $items = $items ? $items : WPLA_ListingQueryHelper::getItemsWithMinMaxAndLowestPrice();
     $changed_product_ids = array();
     $repricing_margin = floatval(get_option('wpla_repricing_margin'));
     $lowest_offer_mode = get_option('wpla_repricing_use_lowest_offer', 0);
     // loop found listings
     foreach ($items as $item) {
         // make sure there is a product - and min/max prices are set (0 != NULL)
         if (!$item->post_id) {
             continue;
         }
         if (!$item->min_price) {
             continue;
         }
         if (!$item->max_price) {
             continue;
         }
         if (!$item->buybox_price && !$item->compet_price) {
             continue;
         }
         // build target price from BuyBox and/or competitor price
         if ($item->buybox_price && !$item->has_buybox) {
             // apply undercut to BuyBox price - if there is a BuyBox price and it's not the seller's
             $target_price = $item->buybox_price - $repricing_margin;
             if ($verbose) {
                 wpla_show_message($item->sku . ': Other seller has BuyBox at ' . $item->buybox_price . ' - your target price: ' . $target_price);
             }
         } elseif ($item->buybox_price && $item->has_buybox && $item->compet_price) {
             // decide based on uppricing mode
             if ($lowest_offer_mode && $item->buybox_price != $item->compet_price) {
                 // seller has BuyBox and there is competition - apply undercut to competitor price (beta)
                 $target_price = $item->compet_price - $repricing_margin;
                 if ($verbose) {
                     wpla_show_message($item->sku . ': You have the BuyBox, but there is a competitor at ' . $item->compet_price . ' - new target price: ' . $target_price);
                 }
             } else {
                 // seller has BuyBox and there is competition - keep price for now
                 $target_price = $item->buybox_price;
                 if ($verbose) {
                     wpla_show_message($item->sku . ': You have the BuyBox - keeping current price: ' . $target_price);
                 }
             }
         } elseif ($item->buybox_price && $item->has_buybox && !$item->compet_price) {
             // seller has BuyBox and NO competition - fall back to max_price
             $target_price = $item->max_price;
             if ($verbose) {
                 wpla_show_message($item->sku . ': You have the BuyBox but there is no competitor - falling back to Max Price: ' . $target_price);
             }
         } elseif ($item->compet_price) {
             $target_price = $item->compet_price;
             if ($verbose) {
                 wpla_show_message($item->sku . ': No BuyBox price - falling back to next competitor: ' . $target_price);
             }
         } else {
             $target_price = $item->max_price;
             if ($verbose) {
                 wpla_show_message($item->sku . ': No BuyBox price, no competitor - falling back to Max Price: ' . $target_price);
             }
         }
         $target_price = round($target_price, 2);
         // update price
         $price_was_changed = self::updateAmazonPrice($item, $target_price, $verbose);
         if ($price_was_changed) {
             $changed_product_ids[] = $item->post_id;
             WPLA()->logger->info('adjustLowestPriceForProducts() - new price for #' . $item->sku . ': ' . $target_price);
         }
     }
     // foreach item
     // echo "<pre>";print_r($changed_product_ids);echo"</pre>";#die();
     // echo "<pre>";print_r($items);echo"</pre>";die();
     return $changed_product_ids;
 }