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 static function orderCanBeFulfilledViaFBA($post, $is_cron = false) { // make sure we have a wp post object if (is_numeric($post)) { $post = get_post($post); } // check if this is an order created by WP-Lister for Amazon $amazon_order_id = get_post_meta($post->ID, '_wpla_amazon_order_id', true); if ($amazon_order_id) { return 'Order was placed on Amazon'; } // check if this order has already been submitted to FBA $submission_status = get_post_meta($post->ID, '_wpla_fba_submission_status', true); if ($submission_status == 'pending') { return __('This order is going to be submitted to Amazon and will be fulfilled via FBA.', 'wpla'); } if ($submission_status == 'success') { return __('This order has been successfully submitted to Amazon and will be fulfilled via FBA.', 'wpla'); } if ($submission_status == 'shipped') { return __('This order has been fulfilled by Amazon.', 'wpla'); } if ($submission_status == 'failed') { // failed submissions can be submitted again - but only manually for now // (automatic resubmittion will require proper error handling for Error 560001: Delivery SLA is not available for destination address - and fallback to Standard shipping) if ($is_cron) { return __('There was a problem submitting this order to be fulfilled by Amazon!', 'wpla'); } } // skip cancelled and pending orders if (!in_array($post->post_status, array('wc-processing', 'wc-completed', 'wc-on-hold'))) { return __('Order status is neither processing nor completed not on hold.', 'wpla'); } // check if FBA is enabled (not really required) // if ( ! get_option( 'wpla_fba_enabled' ) ) return 'FBA support is disabled.'; // get order and order items if (!function_exists('wc_get_order')) { return; } $_order = wc_get_order($post->ID); $order_items = $_order->get_items(); // check if destination country matches fulfillment center $fba_default_fcid = get_option('wpla_fba_fulfillment_center_id', 'AMAZON_NA'); if ('AMAZON_NA' == $fba_default_fcid) { $allowed_countries = array('US'); if (!in_array($_order->shipping_country, $allowed_countries)) { return __('Shipping destination is not within the US.', 'wpla'); } } elseif ('AMAZON_EU' == $fba_default_fcid) { $allowed_countries = array('AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HU', 'HR', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK'); if (!in_array($_order->shipping_country, $allowed_countries)) { return __('Shipping destination is not within the EU.', 'wpla'); } } elseif ('AMAZON_IN' == $fba_default_fcid) { $allowed_countries = array('IN'); if (!in_array($_order->shipping_country, $allowed_countries)) { return __('Shipping destination is not within India.', 'wpla'); } } // check if ordered items are available on FBA $items_available_on_fba = array(); $count_not_available_on_fba = 0; $lm = new WPLA_ListingsModel(); foreach ($order_items as $item) { // skip tax and shipping rows if ($item['type'] != 'line_item') { continue; } // find amazon listing $post_id = $item['variation_id'] ? $item['variation_id'] : $item['product_id']; $listing = $lm->getItemByPostID($post_id); if (!$listing) { $count_not_available_on_fba++; continue; } // check FBA inventory $fba_quantity = $listing->fba_quantity; if ($fba_quantity > 0) { $listing->purchased_qty = $item['qty']; $items_available_on_fba[] = $listing; } else { $count_not_available_on_fba++; } } // each order line item if (empty($items_available_on_fba)) { $msg = __('This order can not be fulfilled by Amazon.', 'wpla') . ' '; $msg .= __('The purchased item(s) are currently not available on FBA.', 'wpla'); return $msg; } if ($count_not_available_on_fba > 0) { $msg = __('This order can not be fulfilled by Amazon.', 'wpla') . ' '; $msg .= __('Not all purchased items are currently available on FBA.', 'wpla'); return $msg; } // this order can be filfilled via FBA - return array of items return $items_available_on_fba; }
function processFbaSubmissionOrderItem($order_item, $_order) { // Flat File FBA Shipment Injection Fulfillment Feed $feed_type = '_POST_FLAT_FILE_FULFILLMENT_ORDER_REQUEST_DATA_'; // use account from first order item (for now) $lm = new WPLA_ListingsModel(); $post_id = $order_item['variation_id'] ? $order_item['variation_id'] : $order_item['product_id']; $listing = $lm->getItemByPostID($post_id); $account_id = $listing->account_id; $account = new WPLA_AmazonAccount($account_id); WPLA()->logger->info('updateFbaSubmissionFeed() ' . $feed_type . ' - post id: ' . $post_id . ' - account id: ' . $account->id); // create pending feed if it doesn't exist if (!($this->id = self::getPendingFeedId($feed_type, null, $account->id))) { # build feed data WPLA()->logger->info('building FBA submission feed...'); $csv = WPLA_FeedDataBuilder::buildFbaSubmissionFeedData($post_id, $_order, $order_item, $listing, $account->id, true); if (!$csv) { WPLA()->logger->warn('no feed data - not creating feed'); return; } // add new feed $this->FeedType = $feed_type; $this->status = 'pending'; $this->account_id = $account->id; $this->date_created = date('Y-m-d H:i:s'); $this->data = $csv; $this->add(); WPLA()->logger->info('added NEW feed - id ' . $this->id); } else { WPLA()->logger->info('found existing feed ' . $this->id); $existing_feed = new WPLA_AmazonFeed($this->id); # append feed data WPLA()->logger->info('updating FBA submission feed...'); $csv = WPLA_FeedDataBuilder::buildFbaSubmissionFeedData($post_id, $_order, $order_item, $listing, $account->id, false); $this->data = $existing_feed->data . $csv; } // update feed $this->line_count = sizeof($csv); $this->FeedProcessingStatus = 'pending'; $this->date_created = date('Y-m-d H:i:s'); $this->update(); WPLA()->logger->info('feed was built and updated - ' . $this->id); }
function wpla_product_admin_notices() { global $post, $post_ID; if (!$post) { return; } if (!$post_ID) { return; } if (!$post->post_type == 'product') { return; } $errors_msg = ''; // warn about missing details $this->checkForMissingData($post); $this->checkForInvalidData($post); // get listing item $lm = new WPLA_ListingsModel(); $listing = $lm->getItemByPostID($post_ID); if (!$listing) { return; } // parse history $history = maybe_unserialize($listing->history); if (empty($history) && $listing->product_type != 'variable') { return; } // echo "<pre>";print_r($history);echo"</pre>";#die(); // show errors and warning on online and failed items only if (!in_array($listing->status, array('online', 'failed'))) { return; } // process errors and warnings $tips_errors = array(); $tips_warnings = array(); if (is_array($history)) { foreach ($history['errors'] as $feed_error) { $tips_errors[] = WPLA_FeedValidator::formatAmazonFeedError($feed_error); } foreach ($history['warnings'] as $feed_error) { $tips_warnings[] = WPLA_FeedValidator::formatAmazonFeedError($feed_error); } } if (!empty($tips_errors)) { $errors_msg .= 'Amazon returned the following error(s) when this product was submitted.' . ' '; $errors_msg .= '(Status: ' . $listing->status . ')<br>'; $errors_msg .= '<small style="color:darkred">' . join('<br>', $tips_errors) . '</small>'; } // check variations for errors if ($listing->product_type == 'variable') { $variations_msg = $errors_msg ? '<br><br>' : ''; $variations_msg .= '<small><a href="#" onclick="jQuery(\'#variation_error_container\').slideToggle();return false;" class="button button-small">' . 'Show errors for all variations' . '</a></small>'; $variations_msg .= '<div id="variation_error_container" style="display:none">'; $variations_have_errors = false; $child_items = $lm->getAllItemsByParentID($post_ID); foreach ($child_items as $child) { $history = maybe_unserialize($child->history); $tips_errors = array(); if (is_array($history)) { foreach ($history['errors'] as $feed_error) { $tips_errors[] = WPLA_FeedValidator::formatAmazonFeedError($feed_error); } // foreach ( $history['warnings'] as $feed_error ) { // $tips_warnings[] = WPLA_FeedValidator::formatAmazonFeedError( $feed_error ); // } } if (!empty($tips_errors)) { $variations_msg .= 'Errors for variation ' . $child->sku . ':' . '<br>'; $variations_msg .= '<small style="color:darkred">' . join('<br>', $tips_errors) . '</small><br><br>'; $variations_have_errors = true; } } $variations_msg .= '</div>'; if ($variations_have_errors) { $errors_msg .= $variations_msg; } } if ($errors_msg) { self::showMessage($errors_msg, 1, 1); } }