public function process_product_meta_variable($post_id) { WPLA()->logger->info('process_product_meta_variable() - ' . $post_id); if (!isset($_POST['variable_sku'])) { return; } $variable_post_id = $_POST['variable_post_id']; $variable_amazon_product_id = $_POST['variable_amazon_product_id']; $variable_amazon_id_type = $_POST['variable_amazon_id_type']; $variable_amazon_asin = $_POST['variable_amazon_asin']; $variable_sku = $_POST['variable_sku']; $variable_amazon_price = isset($_POST['variable_amazon_price']) ? $_POST['variable_amazon_price'] : ''; $variable_amazon_minimum_price = isset($_POST['variable_amazon_minimum_price']) ? $_POST['variable_amazon_minimum_price'] : ''; $variable_amazon_maximum_price = isset($_POST['variable_amazon_maximum_price']) ? $_POST['variable_amazon_maximum_price'] : ''; $variable_amazon_condition_type = isset($_POST['variable_amazon_condition_type']) ? $_POST['variable_amazon_condition_type'] : ''; $variable_amazon_condition_note = isset($_POST['variable_amazon_condition_note']) ? $_POST['variable_amazon_condition_note'] : ''; $variable_amazon_is_disabled = isset($_POST['variable_amazon_is_disabled']) ? $_POST['variable_amazon_is_disabled'] : ''; // convert decimal comma for all price fields $variable_amazon_price = str_replace(',', '.', $variable_amazon_price); $variable_amazon_minimum_price = str_replace(',', '.', $variable_amazon_minimum_price); $variable_amazon_maximum_price = str_replace(',', '.', $variable_amazon_maximum_price); $lm = new WPLA_ListingsModel(); $all_variations_with_SKU = array(); $all_variations_with_ASIN = array(); $max_loop = max(array_keys($_POST['variable_post_id'])); for ($i = 0; $i <= $max_loop; $i++) { if (!isset($variable_post_id[$i])) { continue; } $variation_id = (int) $variable_post_id[$i]; // Update post meta update_post_meta($variation_id, '_amazon_product_id', trim($variable_amazon_product_id[$i])); update_post_meta($variation_id, '_amazon_id_type', $variable_amazon_id_type[$i]); update_post_meta($variation_id, '_wpla_asin', trim($variable_amazon_asin[$i])); update_post_meta($variation_id, '_amazon_price', isset($variable_amazon_price[$i]) ? trim($variable_amazon_price[$i]) : ''); update_post_meta($variation_id, '_amazon_minimum_price', isset($variable_amazon_minimum_price[$i]) ? trim($variable_amazon_minimum_price[$i]) : ''); update_post_meta($variation_id, '_amazon_maximum_price', isset($variable_amazon_maximum_price[$i]) ? trim($variable_amazon_maximum_price[$i]) : ''); update_post_meta($variation_id, '_amazon_condition_type', isset($variable_amazon_condition_type[$i]) ? trim($variable_amazon_condition_type[$i]) : ''); update_post_meta($variation_id, '_amazon_condition_note', isset($variable_amazon_condition_note[$i]) ? trim($variable_amazon_condition_note[$i]) : ''); update_post_meta($variation_id, '_amazon_is_disabled', isset($variable_amazon_is_disabled[$i]) ? $variable_amazon_is_disabled[$i] : ''); // if ( $variable_amazon_product_id[$i] !== 'parent' ) // update_post_meta( $variation_id, '_amazon_product_id', $variable_amazon_product_id[$i] ); // else // delete_post_meta( $variation_id, '_amazon_product_id' ); // update min/max prices in listings table if (isset($_POST['variable_amazon_minimum_price'])) { $min_price = isset($variable_amazon_minimum_price[$i]) ? $variable_amazon_minimum_price[$i] : ''; $max_price = isset($variable_amazon_maximum_price[$i]) ? $variable_amazon_maximum_price[$i] : ''; $data = array(); if ($min_price || $max_price) { if ($listing = $lm->getItemByPostID($variation_id)) { if ($min_price != $listing->min_price) { $data['min_price'] = $min_price; $data['pnq_status'] = 1; // mark as changed } if ($max_price != $listing->max_price) { $data['max_price'] = $max_price; $data['pnq_status'] = 1; // mark as changed } // update listing if (!empty($data)) { $lm->updateWhere(array('id' => $listing->id), $data); } } } } // collect (matched) variations with ASIN if ($variable_amazon_asin[$i]) { $all_variations_with_ASIN[$variation_id] = $variable_amazon_asin[$i]; } // collect all variations with SKU if ($variable_sku[$i]) { $all_variations_with_SKU[$variation_id] = $variable_sku[$i]; } } // each variation WPLA()->logger->info('Variations with ASIN: ' . print_r($all_variations_with_ASIN, 1)); WPLA()->logger->info('Variations with SKU : ' . print_r($all_variations_with_SKU, 1)); // process matched variations // check all variations with ASIN and add missing ones to listings table if (!empty($all_variations_with_ASIN)) { $lm = new WPLA_ListingsModel(); $default_account_id = get_option('wpla_default_account_id', 1); if (!$default_account_id) { return; } // *** foreach ($all_variations_with_ASIN as $variation_id => $asin) { // check if this ASIN / ID already exist - skip if it does WPLA()->logger->info("searching for existing listing for #{$variation_id} / {$asin}"); if ($lm->getItemByASIN($asin, false)) { continue; } if ($lm->getItemByPostID($variation_id)) { continue; } WPLA()->logger->info("no listing found for variation #{$variation_id} / {$asin}"); // skip hidden variations if (get_post_meta($variation_id, '_amazon_is_disabled', true) == 'on') { continue; } // insert matched listing $success = $lm->insertMatchedProduct($variation_id, $asin, $default_account_id); $error_msg = isset($lm->lastError) ? $lm->lastError : ''; if ($success) { // TODO: use persistent admin message WPLA()->logger->info("Matched variation #{$variation_id} / {$asin} - {$error_msg}"); } else { echo "Failed to match variation #{$variation_id} - please report this to support: {$error_msg}"; WPLA()->logger->error("Failed to match variation #{$variation_id} / {$asin} - {$error_msg}"); } } // each matched variation } // if $all_variations_with_ASIN // add missing variations // if the parent product has a listing item, then check for and add missing variation listings $lm = new WPLA_ListingsModel(); $parent_listing = $lm->getItemByPostID($post_id); if ($parent_listing) { // get account from parent listing $account = WPLA_AmazonAccount::getAccount($parent_listing->account_id); if (!$account) { return; } foreach ($all_variations_with_SKU as $variation_id => $sku) { // check if this SKU / ID already exist - skip if it does if ($lm->getItemBySKU($sku, false)) { continue; } if ($lm->getItemByPostID($variation_id)) { continue; } WPLA()->logger->info("no listing found for missing variation #{$variation_id} / {$sku}"); // check if this variation has a UPC/EAN set - skip if empty (unless brand registry is enabled) $_amazon_product_id = get_post_meta($variation_id, '_amazon_product_id', true); if (!$_amazon_product_id && !$account->is_reg_brand) { continue; } // skip hidden variations if (get_post_meta($variation_id, '_amazon_is_disabled', true) == 'on') { continue; } // insert variation listing $success = $lm->insertMissingVariation($variation_id, $sku, $parent_listing); $error_msg = isset($lm->lastError) ? $lm->lastError : ''; if ($success) { // TODO: use persistent admin message WPLA()->logger->info("Matched missing variation #{$variation_id} / {$sku} - {$error_msg}"); } else { echo "Failed to match missing variation #{$variation_id} - please report this to support: {$error_msg}"; WPLA()->logger->error("Failed to match missing variation #{$variation_id} / {$sku} - {$error_msg}"); } } // each variation } // if parent listing exists }
public function processListingDataResults($feed_rows, $result_rows) { $lm = new WPLA_ListingsModel(); // index results by SKU $results = array(); foreach ($result_rows as $r) { if (!isset($r['sku']) && isset($r['SKU'])) { $r['sku'] = $r['SKU']; } // translate column SKU -> sku if (!isset($r['sku']) || empty($r['sku'])) { continue; } $results[$r['sku']][] = $r; WPLA()->logger->info('result sku: ' . $r['sku']); } // process each result row foreach ($feed_rows as $row) { $listing_data = array(); $row_sku = isset($row['item_sku']) ? $row['item_sku'] : $row['sku']; if (!$row_sku) { WPLA()->logger->warn('skipping row without SKU: ' . print_r($row, 1)); continue; } $row_results = isset($results[$row_sku]) ? $results[$row_sku] : false; WPLA()->logger->info('processing feed sku: ' . $row_sku); // check if this is a delete feed (Inventory Loader) $add_delete_column = isset($row['add-delete']) ? $row['add-delete'] : ''; $is_delete_feed = $add_delete_column == 'x' ? true : false; // if there are no result rows for this SKU, set status to 'online' if (!$row_results) { if ($is_delete_feed) { $listing = $lm->getItemBySKU($row_sku); if (!$listing) { continue; } if ($listing->status == 'trashed') { $lm->deleteItem($listing->id); WPLA()->logger->info('DELETED listing ID ' . $listing->id . ' SKU: ' . $row_sku); } else { WPLA()->logger->warn('INVALID listing status for deletion - ID ' . $listing->id . ' / SKU: ' . $row_sku . ' / status: ' . $listing->status); } continue; } $listing_data['status'] = 'online'; $listing_data['history'] = ''; $lm->updateWhere(array('sku' => $row_sku, 'account_id' => $this->account_id), $listing_data); WPLA()->logger->info('changed status to online: ' . $row_sku); continue; } // handle errors and warnings $errors = array(); $warnings = array(); $processed_keys = array(); foreach ($row_results as $row_result) { // translate error-type if ($row_result['error-type'] == 'Fehler') { $row_result['error-type'] = 'Error'; } // amazon.de if ($row_result['error-type'] == 'Warnung') { $row_result['error-type'] = 'Warning'; } if ($row_result['error-type'] == 'Erreur') { $row_result['error-type'] = 'Error'; } // amazon.fr if ($row_result['error-type'] == 'Avertissement') { $row_result['error-type'] = 'Warning'; } // compute hash to identify duplicate errors $row_key = md5($row_result['sku'] . $row_result['error-code'] . $row_result['error-type'] . $row_result['original-record-number']); // store feed id in error array $row_result['feed_id'] = $this->id; if ('Error' == $row_result['error-type']) { WPLA()->logger->info('error: ' . $row_sku . ' - ' . $row_key . ' - ' . $row_result['error-message']); if (!in_array($row_key, $processed_keys)) { $errors[] = $row_result; $processed_keys[] = $row_key; } } elseif ('Warning' == $row_result['error-type']) { WPLA()->logger->info('warning: ' . $row_sku . ' - ' . $row_key . ' - ' . $row_result['error-message']); if (!in_array($row_key, $processed_keys)) { $warnings[] = $row_result; $processed_keys[] = $row_key; } } } // foreach result row // update listing if (!empty($errors)) { $listing_data['status'] = 'failed'; $listing_data['history'] = serialize(array('errors' => $errors, 'warnings' => $warnings)); $lm->updateWhere(array('sku' => $row_sku, 'account_id' => $this->account_id), $listing_data); WPLA()->logger->info('changed status to FAILED: ' . $row_sku); $this->errors = array_merge($this->errors, $errors); $this->warnings = array_merge($this->warnings, $warnings); } elseif (!empty($warnings)) { $listing_data['status'] = $is_delete_feed ? 'trashed' : 'online'; $listing_data['history'] = serialize(array('errors' => $errors, 'warnings' => $warnings)); $lm->updateWhere(array('sku' => $row_sku, 'account_id' => $this->account_id), $listing_data); WPLA()->logger->info('changed status to online: ' . $row_sku); $this->warnings = array_merge($this->warnings, $warnings); } } // foreach row }
public function fixNewVariationListings($variations, $parent_listing) { WPLA()->logger->info("fixNewVariationListings()"); $lm = new WPLA_ListingsModel(); // get post_id of parent which has been created by now // $parent_listing = $lm->getItemByASIN( $parent_listing->asin ); $parent_listing = $lm->getItemBySKU($parent_listing->sku); // catch Invalid argument error if (!is_array($variations)) { WPLA()->logger->error("no variations found for parent variable ASIN {$parent_listing->asin} (not checked)"); WPLA()->logger->error("no variations found for parent variable SKU {$parent_listing->sku}"); WPLA()->logger->error('variations:' . print_r($variations, 1)); // echo 'Error: no variations found for variable ASIN '.$parent_listing->asin.'<br>'; // echo "<pre>variations: ";print_r($variations);echo"</pre>";#die(); return; } foreach ($variations as $var) { $post_id = WPLA_ProductBuilder::getProductIdBySKU($var->sku); if (!$post_id) { WPLA()->logger->warn("fixing SKU {$var->sku} ... no product found for this SKU!!"); continue; } $data = array('post_id' => $post_id, 'parent_id' => $parent_listing->post_id); $lm->updateListing($var->listing_id, $data); WPLA()->logger->info("fixed SKU {$var->sku} - post_id: {$post_id}"); } }
public static function processFBAReportPage($report, $rows, $job, $task) { $listingsModel = new WPLA_ListingsModel(); $errors = array(); // get default fulfillment center ID $fba_default_fcid = get_option('wpla_fba_fulfillment_center_id', 'AMAZON_NA'); // if fallback is enabled, clear FBA data before processing first page $account_id = $report->account_id; $fba_enable_fallback = get_option('wpla_fba_enable_fallback', 0); $fba_only_mode = get_option('wpla_fba_only_mode', 0); if ($task['from_row'] == 1 && $fba_enable_fallback) { // reset FBA info for all items using this account $update_data = array('fba_quantity' => null, 'fba_fcid' => null); $listingsModel->updateWhere(array('account_id' => $account_id), $update_data); } // process rows if (is_array($rows)) { foreach ($rows as $row) { // skip error rows (single element array) if (sizeof($row) <= 1) { $error = new stdClass(); $error->HtmlMessage = strip_tags(reset($row)); $errors[] = $error; continue; } $asin = $row['asin']; $sku = $row['seller-sku']; $fba_quantity = $row['Quantity Available']; $fba_condition = $row['Warehouse-Condition-code']; // skip rows if condition is UNSELLABLE if ($fba_condition == 'UNSELLABLE') { continue; } // if fallback enabled, skip rows with zero quantity if ($fba_quantity == 0 && $fba_enable_fallback && !$fba_only_mode) { continue; } $update_data = array('fba_quantity' => $fba_quantity, 'fba_fcid' => $fba_default_fcid); // update listings table - by SKU // if ( $asin ) $listingsModel->updateWhere( array( 'asin' => $asin ), $update_data ); if ($sku) { $listingsModel->updateWhere(array('sku' => $sku), $update_data); } // update quantity in WooCommerce - only if current stock level is less than FBA quantity if ($listing_item = $listingsModel->getItemBySKU($sku)) { $post_id = $listing_item->post_id; if ($post_id) { // update stock level - if lower than FBA, or FBA only mode enabled $woo_stock = get_post_meta($post_id, '_stock', true); if ($woo_stock < $fba_quantity || $fba_only_mode == 1) { update_post_meta($post_id, '_stock', $fba_quantity); $woo_stock = $fba_quantity; // // update out of stock attribute // if ( $fba_quantity > 0 ) { // update_post_meta( $post_id, '_stock_status', 'instock' ); // } else { // update_post_meta( $post_id, '_stock_status', 'outofstock' ); // } } // update stock status based on actual stock - if required $woo_stock_status = get_post_meta($post_id, '_stock_status', true); $new_stock_status = $woo_stock > 0 ? 'instock' : 'outofstock'; if ($new_stock_status != $woo_stock_status) { update_post_meta($post_id, '_stock_status', $new_stock_status); } } // if $post_id } // if $listing_item } } // foreach report row // build response $response = new stdClass(); $response->job = $job; $response->task = $task; $response->errors = $errors; $response->success = true; return $response; }
function processListingItem($item, $order) { global $wpdb; // abort if item data is invalid if (!isset($item->ASIN) && !isset($item->QuantityOrdered)) { $history_message = "Error fetching order line items - request throttled?"; $history_details = array(); $this->addHistory($order->AmazonOrderId, 'request_throttled', $history_message, $history_details); return false; } $order_id = $order->AmazonOrderId; $asin = $item->ASIN; $sku = $item->SellerSKU; $quantity_purchased = $item->QuantityOrdered; // get listing item $lm = new WPLA_ListingsModel(); $listing = $lm->getItemBySKU($sku); // skip if this listing does not exist in WP-Lister if (!$listing) { $history_message = "Skipped unknown SKU {$sku} ({$asin})"; $history_details = array('sku' => $sku, 'asin' => $asin); $this->addHistory($order_id, 'skipped_item', $history_message, $history_details); return true; } // handle FBA orders if ($order->FulfillmentChannel == 'AFN') { // update quantity for FBA orders $fba_quantity = $listing->fba_quantity - $quantity_purchased; $quantity_sold = $listing->quantity_sold + $quantity_purchased; $wpdb->update($wpdb->prefix . 'amazon_listings', array('fba_quantity' => $fba_quantity, 'quantity_sold' => $quantity_sold), array('sku' => $sku)); // add history record $history_message = "FBA quantity reduced by {$quantity_purchased} for listing {$sku} ({$asin}) - FBA stock {$fba_quantity} ({$quantity_sold} sold)"; $history_details = array('fba_quantity' => $fba_quantity, 'sku' => $sku, 'asin' => $asin, 'qty_purchased' => $quantity_purchased, 'listing_id' => $listing->id); $this->addHistory($order_id, 'reduce_stock', $history_message, $history_details); } else { // update quantity for non-FBA orders $quantity_total = $listing->quantity - $quantity_purchased; $quantity_sold = $listing->quantity_sold + $quantity_purchased; $wpdb->update($wpdb->prefix . 'amazon_listings', array('quantity' => $quantity_total, 'quantity_sold' => $quantity_sold), array('sku' => $sku)); // add history record $history_message = "Quantity reduced by {$quantity_purchased} for listing {$sku} ({$asin}) - new stock: {$quantity_total} ({$quantity_sold} sold)"; $history_details = array('newstock' => $quantity_total, 'sku' => $sku, 'asin' => $asin, 'qty_purchased' => $quantity_purchased, 'listing_id' => $listing->id); $this->addHistory($order_id, 'reduce_stock', $history_message, $history_details); } // mark listing as sold when last item is sold // if ( $quantity_total == 0 ) { // $wpdb->update( $wpdb->prefix.'amazon_listings', // array( 'status' => 'sold', 'date_finished' => $data['date_created'], ), // array( 'sku' => $sku ) // ); // WPLA()->logger->info( 'marked item '.$sku.' as SOLD '); // } return true; }