options = new AmzFulfillment_Options(); $this->options->load(); $this->orderUpdateTime = new AmzFulfillment_Data_OrderUpdateTime(); add_action('woocommerce_order_actions', array ($this, 'addMetaboxAction')); add_action('admin_footer-edit.php', array($this, 'addBulkAction')); add_action('woocommerce_order_action_' . self::METABOX_ACTION, array($this, 'doFulfillment')); add_action('load-edit.php', array($this, 'doBulkFulfillment')); add_action('woocommerce_order_status_changed', array($this, 'orderStatusChanged')); } /** * addMetaboxAction * * Add amazon option to $actions array * * @param array $actions * @return array */ public function addMetaboxAction($actions) { $actions[self::METABOX_ACTION] = 'Amazon fulfillment'; return $actions; } /** * addBulkAction */ public function addBulkAction() { global $post_type; if ($post_type == 'shop_order') { printf(""); } } /** * doFulfillment * * @param WC_Order $order */ public function doFulfillment($order) { AmzFulfillment_Core::instance()->doAmazonFulfillment($order->get_id()); } /** * doBulkFulfillment */ public function doBulkFulfillment() { $wpListTable = _get_list_table('WP_Posts_List_Table'); $action = $wpListTable->current_action(); if($action !== self::BULK_ACTION) { return; } $orderIds = array_map('absint', (array) $_REQUEST['post']); if(!count($orderIds)) { AmzFulfillment_Core::instance()->addAdminMessage(AmzFulfillment_Core::WARN, 'No orders selected for fulfillment'); return; } AmzFulfillment_Core::instance()->getLog()->add(sprintf('Start bulk fulfillment for orders: %s', implode(', ', $orderIds))); foreach($orderIds as $orderId) { AmzFulfillment_Core::instance()->doAmazonFulfillment($orderId); } } /** * setProductAvailable * * @param int $productId * @param boolean $available */ public function setProductAvailable($productId, $available) { $product = wc_get_product($productId); if($product == null) { throw new RuntimeException(sprintf('Product not found: %d', $productId)); } if($available) { $product->set_stock_status('instock'); } else { $product->set_stock_status('outofstock'); } $product->save(); } /** * getProducts * * proucts with propperties: * - title * - sku * - stock * - productId * - varriantId * * @return array */ public function getProducts() { global $wpdb; $products = array(); $query = " SELECT p.ID, p.post_title, ts.slug FROM `%sposts` AS p INNER JOIN `%sterm_relationships` AS t ON p.ID = t.object_id INNER JOIN `%sterm_taxonomy` AS tt ON t.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN `%sterms` AS ts ON tt.term_id = ts.term_id WHERE tt.taxonomy = 'product_type' AND p.post_type = 'product' AND p.post_status = 'publish'"; $results = $wpdb->get_results(sprintf($query, $wpdb->prefix, $wpdb->prefix, $wpdb->prefix, $wpdb->prefix)); foreach($results as $result) { if($result->slug == "simple") { $products[] = array( 'title' => $result->post_title, 'sku' => get_post_meta($result->ID, '_sku', true), 'stock' => get_post_meta($result->ID, '_stock', true), 'productId' => $result->ID, 'varriantId' => false ); } elseif($result->slug == "variable"){ $args = array('post_type' => 'product_variation', 'post_status' => array( 'publish' ), 'post_parent' => $result->ID); $variations = get_posts($args); foreach($variations as $variation) { $products[] = array( 'title' => $result->post_title, 'sku' => get_post_meta($variation->ID, '_sku', true), 'stock' => get_post_meta($variation->ID, '_stock', true), 'productId' => $result->ID, 'varriantId' => $variation->ID ); } } } return $products; } /** * getProductBySku * * @param string $sku * @return array|NULL */ public function getProductBySku($sku) { foreach($this->getProducts() as $product) { if($product['sku'] == $sku) { return $product; } } return NULL; } /** * getProductIdBySku * * @param string $sku * @throws Exception * @return int id */ public function getProductIdBySku($sku) { global $wpdb; $query = "SELECT pm.post_id FROM %spostmeta AS pm JOIN %sposts AS p ON pm.post_id = p.ID AND pm.meta_value='%s' AND pm.meta_key='_sku' AND p.post_status='publish'"; $result = $wpdb->get_results(sprintf($query, $wpdb->prefix, $wpdb->prefix, $sku)); if(!isset($result[0])) { throw new Exception('No product found with sku ' . $sku); } return intval($result[0]->post_id); } /** * setStock * * @param int $productId * @param int $stock */ public function setStock($productId, $stock) { update_post_meta($productId, '_stock', $stock); } /** * getCurrency * * Get the currency code which is configure in WooCommerce * * @return string */ public function getCurrency() { return get_option('woocommerce_currency'); } /** * getSkus * * Get skus from all products and varriations * * @return array */ public function getSkus() { $skus = array(); foreach($this->getProducts() as $product) { if(!empty($product['sku'])) { $skus[] = $product['sku']; } } return $skus; } /** * getOrder * * @param unknown $orderId * @throws RuntimeException * @return WC_Order */ public function getOrder($orderId) { if(!$this->existOrder($orderId)) { throw new RuntimeException(sprintf('Order not found: %d', $orderId)); } else { return new WC_Order($orderId); } } /** * existOrder * * @return boolean */ public function existOrder($orderId) { try { new WC_Order($orderId); return true; } catch(Exception $e) { return false; } } /** * addNote * * @param int $orderId * @param string $note */ public function addNote($orderId, $note) { if($this->existOrder($orderId)) { (new WC_Order($orderId))->add_order_note($note); } } /** * setStatus * * @param int $orderId * @param string $status * @throws InvalidArgumentException * @throws RuntimeException */ public function setStatus($orderId, $status) { if(!array_key_exists($status, AmzFulfillment_WooCommerceStatus::$orderStatus)) { throw new InvalidArgumentException('Invalid order status type: ' . $status); } if(!$this->existOrder($orderId)) { throw new RuntimeException(sprintf('Order not found: %d', $orderId)); } $order = new WC_Order($orderId); if($order->get_status() == $status) { throw new RuntimeException('Order is already in the status to be set: ' . $status); } $order->set_status($status, 'Order changed by Amazing Fullfilment plugin to ' . $status, true); $order->save(); } /** * orderStatusChanged * * An order has changed its status * * @param int $orderId */ public function orderStatusChanged($orderId) { $order = new WC_Order($orderId); $orderUpdateTime = $this->orderUpdateTime->get($orderId); if(time() - $orderUpdateTime < self::ORDER_LOCK_TIME) { return; } $status = $order->get_status(); switch($status) { case AmzFulfillment_WooCommerceStatus::PENDING: AmzFulfillment_Core::instance()->getEventHandler()->createEvent(AmzFulfillment_Event::WOOCOMMERCE_ORDER_PENDING, $orderId); break; case AmzFulfillment_WooCommerceStatus::PROCESSING: AmzFulfillment_Core::instance()->getEventHandler()->createEvent(AmzFulfillment_Event::WOOCOMMERCE_ORDER_PROCESSING, $orderId); break; case AmzFulfillment_WooCommerceStatus::ONHOLD: AmzFulfillment_Core::instance()->getEventHandler()->createEvent(AmzFulfillment_Event::WOOCOMMERCE_ORDER_ONHOLD, $orderId); break; case AmzFulfillment_WooCommerceStatus::COMPLETED: AmzFulfillment_Core::instance()->getEventHandler()->createEvent(AmzFulfillment_Event::WOOCOMMERCE_ORDER_COMPLETED, $orderId); break; case AmzFulfillment_WooCommerceStatus::CANCELLED: AmzFulfillment_Core::instance()->getEventHandler()->createEvent(AmzFulfillment_Event::WOOCOMMERCE_ORDER_CANCELLED, $orderId); break; case AmzFulfillment_WooCommerceStatus::REFUNDED: AmzFulfillment_Core::instance()->getEventHandler()->createEvent(AmzFulfillment_Event::WOOCOMMERCE_ORDER_REFUNDED, $orderId); break; case AmzFulfillment_WooCommerceStatus::FAILED: AmzFulfillment_Core::instance()->getEventHandler()->createEvent(AmzFulfillment_Event::WOOCOMMERCE_ORDER_FAILED, $orderId); break; default: AmzFulfillment_Core::instance()->getLog()->add(sprintf('Error: Order %d changed to unexpected status: %s', $orderId, $status)); break; } $this->orderUpdateTime->set($orderId); } }