From 7933827318f438f26ce8197340fd4d7f9bef2bf4 Mon Sep 17 00:00:00 2001 From: max-baranikov Date: Fri, 26 Feb 2021 15:42:08 +0300 Subject: [PATCH] Optimized work of JobManager commands * Optimized the SQL query for abandoned carts. Added more checks in paymentCCAdd hook * Added check for custom event classes * Added import of all attached categories to the product in Icml * Improved the sync event * Fix error when creating order without items * Fix tests --- retailcrm/lib/RetailcrmCartUploader.php | 53 ++--- retailcrm/lib/RetailcrmCatalog.php | 10 +- retailcrm/lib/RetailcrmHistory.php | 193 ++++++++++-------- retailcrm/lib/RetailcrmJobManager.php | 11 +- .../lib/api/RetailcrmApiPaginatedRequest.php | 2 +- retailcrm/retailcrm.php | 11 +- tests/lib/RetailcrmHistoryTest.php | 32 +++ 7 files changed, 174 insertions(+), 138 deletions(-) diff --git a/retailcrm/lib/RetailcrmCartUploader.php b/retailcrm/lib/RetailcrmCartUploader.php index 86b8773..a3a6528 100644 --- a/retailcrm/lib/RetailcrmCartUploader.php +++ b/retailcrm/lib/RetailcrmCartUploader.php @@ -66,6 +66,11 @@ class RetailcrmCartUploader */ static $syncDelay; + /** + * @var int + */ + static $allowedUpdateInterval; + /** * @var string */ @@ -99,6 +104,7 @@ class RetailcrmCartUploader static::$cartsIds = array(); static::$paymentTypes = array(); static::$syncDelay = 0; + static::$allowedUpdateInterval = 86400; static::$syncStatus = ''; static::$now = new \DateTime(); static::$context = Context::getContext(); @@ -123,7 +129,7 @@ class RetailcrmCartUploader $cartExternalId = RetailcrmTools::getCartOrderExternalId($cart); $cartLastUpdateDate = null; - if (static::isGuestCart($cart) || static::isCartTooOld($cart->date_upd) || static::isCartEmpty($cart)) { + if (static::isGuestCart($cart) || static::isCartEmpty($cart)) { continue; } @@ -198,41 +204,6 @@ class RetailcrmCartUploader return false; } - /** - * Returns true if cart is too old to update. - * - * @param string $cartDateUpd It's $cart->date_upd - * - * @return bool - */ - private static function isCartTooOld($cartDateUpd) - { - try { - $allowedUpdateInterval = new \DateInterval('P1D'); - $cartLastUpdate = \DateTime::createFromFormat('Y-m-d H:i:s', $cartDateUpd); - - if ($cartLastUpdate instanceof \DateTime) { - $cartLastUpdateDiff = $cartLastUpdate->diff(new \DateTime('now')); - - // Workaround for PHP bug: https://bugs.php.net/bug.php?id=49914 - ob_start(); - var_dump($allowedUpdateInterval); - var_dump($cartLastUpdateDiff); - ob_clean(); - ob_end_flush(); - - if ($cartLastUpdateDiff > $allowedUpdateInterval) { - return true; - } - } - } catch (\Exception $exception) { - RetailcrmLogger::writeCaller(__METHOD__, $exception->getMessage()); - RetailcrmLogger::writeNoCaller($exception->getTraceAsString()); - } - - return false; - } - /** * Returns true if cart is empty or if cart emptiness cannot be checked because something gone wrong. * Errors with checking cart emptiness will be correctly written to log. @@ -357,10 +328,16 @@ class RetailcrmCartUploader { $sql = 'SELECT c.id_cart, c.date_upd FROM ' . _DB_PREFIX_ . 'cart AS c - WHERE id_customer != 0 + LEFT JOIN ' . _DB_PREFIX_ . 'customer cus + ON + c.id_customer = cus.id_customer + WHERE c.id_customer != 0 + AND cus.is_guest = 0 ' . Shop::addSqlRestriction(false, 'c') . ' AND TIME_TO_SEC(TIMEDIFF(\'' . pSQL(static::$now->format('Y-m-d H:i:s')) - . '\', date_upd)) >= ' . pSQL(static::$syncDelay) . ' + . '\', c.date_upd)) >= ' . pSQL(static::$syncDelay) . ' + AND TIME_TO_SEC(TIMEDIFF(\'' . pSQL(static::$now->format('Y-m-d H:i:s')) + . '\', c.date_upd)) <= ' . pSQL(static::$allowedUpdateInterval) . ' AND c.id_cart NOT IN(SELECT id_cart from ' . _DB_PREFIX_ . 'orders);'; static::$cartsIds = Db::getInstance()->executeS($sql); } diff --git a/retailcrm/lib/RetailcrmCatalog.php b/retailcrm/lib/RetailcrmCatalog.php index 560bed0..22cc1cd 100644 --- a/retailcrm/lib/RetailcrmCatalog.php +++ b/retailcrm/lib/RetailcrmCatalog.php @@ -137,12 +137,6 @@ class RetailcrmCatalog $products = Product::getProducts($id_lang, $start, $limit, 'name', 'asc'); foreach ($products as $product) { - $category = $product['id_category_default']; - - if (!in_array($category, $categoriesIds)) { - continue; - } - $currentProductCategories = Product::getProductCategories($product['id_product']); $categoriesLeft = array_filter( $currentProductCategories, @@ -275,7 +269,7 @@ class RetailcrmCatalog 'productActivity' => ($available_for_order) ? 'Y' : 'N', 'name' => htmlspecialchars(strip_tags(Product::getProductName($product['id_product'], $offer['id_product_attribute']))), 'productName' => htmlspecialchars(strip_tags($product['name'])), - 'categoryId' => array($category), + 'categoryId' => $categoriesLeft, 'picture' => $pictures, 'url' => $url, 'quantity' => $quantity > 0 ? $quantity : 0, @@ -316,7 +310,7 @@ class RetailcrmCatalog 'productActivity' => ($available_for_order) ? 'Y' : 'N', 'name' => htmlspecialchars(strip_tags($product['name'])), 'productName' => htmlspecialchars(strip_tags($product['name'])), - 'categoryId' => array($category), + 'categoryId' => $categoriesLeft, 'picture' => $pictures, 'url' => $url, 'quantity' => $quantity > 0 ? $quantity : 0, diff --git a/retailcrm/lib/RetailcrmHistory.php b/retailcrm/lib/RetailcrmHistory.php index 36eee89..2408775 100644 --- a/retailcrm/lib/RetailcrmHistory.php +++ b/retailcrm/lib/RetailcrmHistory.php @@ -69,12 +69,11 @@ class RetailcrmHistory if (count($history) > 0) { $historyChanges = static::filterHistory($history, 'customer'); + $end = end($history); + Configuration::updateValue('RETAILCRM_LAST_CUSTOMERS_SYNC', $end['id']); } if (count($historyChanges)) { - $end = end($historyChanges); - Configuration::updateValue('RETAILCRM_LAST_CUSTOMERS_SYNC', $end['id']); - $customersHistory = RetailcrmHistoryHelper::assemblyCustomer($historyChanges); RetailcrmLogger::writeDebugArray(__METHOD__, array('Assembled history:', $customersHistory)); @@ -188,7 +187,6 @@ class RetailcrmHistory $filter = array(); } - $customerFix = array(); $orderFix = array(); $historyChanges = array(); $request = new RetailcrmApiPaginatedRequest(); @@ -203,12 +201,11 @@ class RetailcrmHistory if (count($history) > 0) { $historyChanges = static::filterHistory($history, 'order'); + $end = end($history); + Configuration::updateValue('RETAILCRM_LAST_ORDERS_SYNC', $end['id']); } if (count($historyChanges)) { - $end = end($historyChanges); - Configuration::updateValue('RETAILCRM_LAST_ORDERS_SYNC', $end['id']); - $statuses = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_STATUS'), true))); $cartStatus = (string)(Configuration::get('RETAILCRM_API_SYNCHRONIZED_CART_STATUS')); $deliveries = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_DELIVERY'), true))); @@ -543,16 +540,30 @@ class RetailcrmHistory $product_id = $product_id[0]; } + $productPriceStatic = Product::getPriceStatic( + (int)$product->id, + true, + null, + 6, + null, + false, + true, + 1, + false, + null, + (int)$cart->id + ); + if ($product_attribute_id != 0) { $productName = htmlspecialchars( strip_tags(Product::getProductName($product_id, $product_attribute_id)) ); $combinationPrice = Combination::getPrice($product_attribute_id); - $productPrice = $combinationPrice > 0 ? $product->getPrice() + $combinationPrice : $product->getPrice(); + $productPrice = $combinationPrice > 0 ? $productPriceStatic + $combinationPrice : $productPriceStatic; } else { $productName = htmlspecialchars(strip_tags($product->name)); - $productPrice = $product->getPrice(); + $productPrice = $productPriceStatic; } $product_list[] = array( @@ -676,7 +687,7 @@ class RetailcrmHistory ) ); - $carrier->add(false, false); + $carrier->add(true, false); /* * collect order ids for single fix request */ @@ -689,17 +700,21 @@ class RetailcrmHistory $orderDetail->createList($newOrder, $cart, $newOrder->current_state, $product_list); - if (!empty($customerFix)) { - self::$api->customersFixExternalIds($customerFix); - } - if (!empty($orderFix)) { self::$api->ordersFixExternalIds($orderFix); } + + static::updateOrderItems($newOrder->id); + //TODO // Also update orders numbers after creating them in PrestaShop. // Current logic will result in autogenerated order numbers in retailCRM if // order was placed via retailCRM interface. + // $upOrder = array( + // 'externalId' => $newOrder->id, + // 'number' => $newOrder->reference + // ); + // self::$api->ordersEdit($upOrder); } else { $order = $order_history; @@ -734,10 +749,12 @@ class RetailcrmHistory ->build(); $address = $customerBuilder->getData()->getCustomerAddress(); - $address->id = $orderToUpdate->id_address_delivery; + if(!is_null($address)) { + $address->id = $orderToUpdate->id_address_delivery; - $address->update(); - $orderToUpdate->update(); + $address->update(); + $orderToUpdate->update(); + } } } @@ -748,42 +765,42 @@ class RetailcrmHistory $dtype = $order['delivery']['code']; $dcost = !empty($order['delivery']['cost']) ? $order['delivery']['cost'] : null; - if (isset($deliveries[$dtype]) && $deliveries[$dtype] != null) { - if ($deliveries[$dtype] != $orderToUpdate->id_carrier or $dcost != null) { - if ($dtype != null) { - if (property_exists($orderToUpdate, 'id_order_carrier')) { - $idOrderCarrier = $orderToUpdate->id_order_carrier; - } elseif (method_exists($orderToUpdate, 'getIdOrderCarrier')) { - $idOrderCarrier = $orderToUpdate->getIdOrderCarrier(); - } - - $orderCarrier = new OrderCarrier($idOrderCarrier); - $orderCarrier->id_carrier = $deliveries[$dtype]; - } - - if ($dtype != null) { - $orderCarrier->id_carrier = $deliveries[$dtype]; - } - - if ($dcost != null) { - $orderCarrier->shipping_cost_tax_incl = $dcost; - $orderCarrier->shipping_cost_tax_excl = $dcost; - } - - $orderCarrier->id_order = $orderToUpdate->id; - - RetailcrmLogger::writeDebug( - __METHOD__, - sprintf( - '<%d> %s::%s', - $orderCarrier->id, - get_class($orderCarrier), - 'update' - ) - ); - - $orderCarrier->update(); + if ( + isset($deliveries[$dtype]) && $deliveries[$dtype] != null && + ($deliveries[$dtype] != $orderToUpdate->id_carrier or $dcost != null) + ) { + if (property_exists($orderToUpdate, 'id_order_carrier')) { + $idOrderCarrier = $orderToUpdate->id_order_carrier; + } elseif (method_exists($orderToUpdate, 'getIdOrderCarrier')) { + $idOrderCarrier = $orderToUpdate->getIdOrderCarrier(); + } else { + $idOrderCarrier = null; } + + $orderCarrier = new OrderCarrier($idOrderCarrier); + + if ($dtype != null) { + $orderCarrier->id_carrier = $deliveries[$dtype]; + } + + if ($dcost != null) { + $orderCarrier->shipping_cost_tax_incl = $dcost; + $orderCarrier->shipping_cost_tax_excl = $dcost; + } + + $orderCarrier->id_order = $orderToUpdate->id; + + RetailcrmLogger::writeDebug( + __METHOD__, + sprintf( + '<%d> %s::%s', + $orderCarrier->id, + get_class($orderCarrier), + 'update' + ) + ); + + $orderCarrier->update(); } } @@ -868,19 +885,17 @@ class RetailcrmHistory $orderHistory->save(); - $orderToUpdate->current_state = $statuses[$stype]; - RetailcrmLogger::writeDebug( __METHOD__, sprintf( ' %s::%s', $orderToUpdate->id, - get_class($orderToUpdate), - 'update' + get_class($orderHistory), + 'changeIdOrderState' ) ); - $orderToUpdate->update(); + $orderHistory->changeIdOrderState($statuses[$stype], $orderToUpdate->id,true); } } } @@ -1302,35 +1317,7 @@ class RetailcrmHistory ); if ($orderDetail->save()) { - $upOrderItems = array( - 'externalId' => $orderDetail->id_order, - ); - - $orderdb = new Order($orderDetail->id_order); - - foreach ($orderdb->getProducts() as $item) { - if (isset($item['product_attribute_id']) && $item['product_attribute_id'] > 0) { - $productId = $item['product_id'] . '#' . $item['product_attribute_id']; - } else { - $productId = $item['product_id']; - } - - $upOrderItems['items'][] = array( - "externalIds" => array( - array( - 'code' =>'prestashop', - 'value' => $productId."_".$item['id_order_detail'], - ) - ), - 'initialPrice' => $item['unit_price_tax_incl'], - 'quantity' => $item['product_quantity'], - 'offer' => array('externalId' => $productId), - 'productName' => $item['product_name'], - ); - } - - unset($orderdb); - self::$api->ordersEdit($upOrderItems); + static::updateOrderItems($orderDetail->id_order); } unset($orderDetail); @@ -1680,5 +1667,39 @@ class RetailcrmHistory $object->product_name = implode('', array('\'', $name, '\'')); } } + + private static function updateOrderItems($orderId) + { + $upOrderItems = array( + 'externalId' => $orderId, + ); + + $orderdb = new Order($orderId); + + foreach ($orderdb->getProducts() as $item) { + if (isset($item['product_attribute_id']) && $item['product_attribute_id'] > 0) { + $productId = $item['product_id'] . '#' . $item['product_attribute_id']; + } else { + $productId = $item['product_id']; + } + + $upOrderItems['items'][] = array( + "externalIds" => array( + array( + 'code' =>'prestashop', + 'value' => $productId."_".$item['id_order_detail'], + ) + ), + 'initialPrice' => $item['unit_price_tax_incl'], + 'quantity' => $item['product_quantity'], + 'offer' => array('externalId' => $productId), + 'productName' => $item['product_name'] + ); + } + + unset($orderdb); + if(isset($upOrderItems['items'])) + self::$api->ordersEdit($upOrderItems); + } } diff --git a/retailcrm/lib/RetailcrmJobManager.php b/retailcrm/lib/RetailcrmJobManager.php index e9ce2ed..0cb882b 100644 --- a/retailcrm/lib/RetailcrmJobManager.php +++ b/retailcrm/lib/RetailcrmJobManager.php @@ -286,11 +286,18 @@ class RetailcrmJobManager $jobName = self::escapeJobName($job); $jobFile = implode( DIRECTORY_SEPARATOR, - array(_PS_ROOT_DIR_, 'modules', 'retailcrm', 'lib', 'events', $jobName . '.php') + array(_PS_ROOT_DIR_, 'modules', 'retailcrm_custom','classes', 'lib', 'events', $jobName . '.php') ); if (!file_exists($jobFile)) { - throw new \RetailcrmJobManagerException('Cannot find job', $job); + $jobFile = implode( + DIRECTORY_SEPARATOR, + array(_PS_ROOT_DIR_, 'modules', 'retailcrm', 'lib', 'events', $jobName . '.php') + ); + + if (!file_exists($jobFile)) { + throw new \RetailcrmJobManagerException('Cannot find job', $job); + } } try { diff --git a/retailcrm/lib/api/RetailcrmApiPaginatedRequest.php b/retailcrm/lib/api/RetailcrmApiPaginatedRequest.php index 777717c..c6f1c1d 100644 --- a/retailcrm/lib/api/RetailcrmApiPaginatedRequest.php +++ b/retailcrm/lib/api/RetailcrmApiPaginatedRequest.php @@ -158,7 +158,7 @@ class RetailcrmApiPaginatedRequest ); if ($response instanceof RetailcrmApiResponse && $response->offsetExists($this->dataKey)) { - $this->data = array_merge($response[$this->dataKey]); + $this->data = array_merge($this->data, $response[$this->dataKey]); $page = $response['pagination']['currentPage'] + 1; } diff --git a/retailcrm/retailcrm.php b/retailcrm/retailcrm.php index 25229e8..5bce5c7 100644 --- a/retailcrm/retailcrm.php +++ b/retailcrm/retailcrm.php @@ -667,6 +667,9 @@ class RetailCRM extends Module $externalId = false; + if(empty($params['cart'])) + return false; + $response = $this->api->ordersGet(RetailcrmTools::getCartOrderExternalId($params['cart'])); if ($response !== false && isset($response['order'])) { @@ -674,9 +677,11 @@ class RetailCRM extends Module } else { $order = Order::getByCartId($params['cart']->id); - $response = $this->api->ordersGet($order->id); - if ($response !== false && isset($response['order'])) { - $externalId = $order->id; + if($order !== null) { + $response = $this->api->ordersGet($order->id); + if ($response !== false && isset($response['order'])) { + $externalId = $order->id; + } } } diff --git a/tests/lib/RetailcrmHistoryTest.php b/tests/lib/RetailcrmHistoryTest.php index d9e872c..849b3d2 100644 --- a/tests/lib/RetailcrmHistoryTest.php +++ b/tests/lib/RetailcrmHistoryTest.php @@ -16,6 +16,7 @@ class RetailcrmHistoryTest extends RetailcrmTestCase 'customersHistory', 'ordersHistory', 'ordersGet', + 'ordersEdit', 'customersGet', 'customersFixExternalIds', 'ordersFixExternalIds', @@ -200,6 +201,17 @@ class RetailcrmHistoryTest extends RetailcrmTestCase ) ); + $this->apiMock->expects($this->any()) + ->method('ordersEdit') + ->willReturn( + new RetailcrmApiResponse( + '200', + json_encode( + $this->getEditedOrder($this->getApiOrder()) + ) + ) + ); + $this->orderCreate($this->apiMock); } @@ -229,6 +241,17 @@ class RetailcrmHistoryTest extends RetailcrmTestCase ) ); + $this->apiMock->expects($this->any()) + ->method('ordersEdit') + ->willReturn( + new RetailcrmApiResponse( + '200', + json_encode( + $this->getEditedOrder($this->getApiOrderWitchCorporateCustomer()) + ) + ) + ); + $this->orderCreate($this->apiMock); } @@ -321,6 +344,15 @@ class RetailcrmHistoryTest extends RetailcrmTestCase ); } + private function getEditedOrder($orderData) + { + return array( + 'success' => true, + 'id' => $orderData['id'], + 'order' => $orderData + ); + } + private function getApiOrder() { $order = array(