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
This commit is contained in:
max-baranikov 2021-02-26 15:42:08 +03:00 committed by GitHub
parent f6f330c559
commit 7933827318
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 174 additions and 138 deletions

View File

@ -66,6 +66,11 @@ class RetailcrmCartUploader
*/ */
static $syncDelay; static $syncDelay;
/**
* @var int
*/
static $allowedUpdateInterval;
/** /**
* @var string * @var string
*/ */
@ -99,6 +104,7 @@ class RetailcrmCartUploader
static::$cartsIds = array(); static::$cartsIds = array();
static::$paymentTypes = array(); static::$paymentTypes = array();
static::$syncDelay = 0; static::$syncDelay = 0;
static::$allowedUpdateInterval = 86400;
static::$syncStatus = ''; static::$syncStatus = '';
static::$now = new \DateTime(); static::$now = new \DateTime();
static::$context = Context::getContext(); static::$context = Context::getContext();
@ -123,7 +129,7 @@ class RetailcrmCartUploader
$cartExternalId = RetailcrmTools::getCartOrderExternalId($cart); $cartExternalId = RetailcrmTools::getCartOrderExternalId($cart);
$cartLastUpdateDate = null; $cartLastUpdateDate = null;
if (static::isGuestCart($cart) || static::isCartTooOld($cart->date_upd) || static::isCartEmpty($cart)) { if (static::isGuestCart($cart) || static::isCartEmpty($cart)) {
continue; continue;
} }
@ -198,41 +204,6 @@ class RetailcrmCartUploader
return false; 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. * 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. * 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 $sql = 'SELECT c.id_cart, c.date_upd
FROM ' . _DB_PREFIX_ . 'cart AS c 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') . ' ' . Shop::addSqlRestriction(false, 'c') . '
AND TIME_TO_SEC(TIMEDIFF(\'' . pSQL(static::$now->format('Y-m-d H:i:s')) 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);'; AND c.id_cart NOT IN(SELECT id_cart from ' . _DB_PREFIX_ . 'orders);';
static::$cartsIds = Db::getInstance()->executeS($sql); static::$cartsIds = Db::getInstance()->executeS($sql);
} }

View File

@ -137,12 +137,6 @@ class RetailcrmCatalog
$products = Product::getProducts($id_lang, $start, $limit, 'name', 'asc'); $products = Product::getProducts($id_lang, $start, $limit, 'name', 'asc');
foreach ($products as $product) { foreach ($products as $product) {
$category = $product['id_category_default'];
if (!in_array($category, $categoriesIds)) {
continue;
}
$currentProductCategories = Product::getProductCategories($product['id_product']); $currentProductCategories = Product::getProductCategories($product['id_product']);
$categoriesLeft = array_filter( $categoriesLeft = array_filter(
$currentProductCategories, $currentProductCategories,
@ -275,7 +269,7 @@ class RetailcrmCatalog
'productActivity' => ($available_for_order) ? 'Y' : 'N', 'productActivity' => ($available_for_order) ? 'Y' : 'N',
'name' => htmlspecialchars(strip_tags(Product::getProductName($product['id_product'], $offer['id_product_attribute']))), 'name' => htmlspecialchars(strip_tags(Product::getProductName($product['id_product'], $offer['id_product_attribute']))),
'productName' => htmlspecialchars(strip_tags($product['name'])), 'productName' => htmlspecialchars(strip_tags($product['name'])),
'categoryId' => array($category), 'categoryId' => $categoriesLeft,
'picture' => $pictures, 'picture' => $pictures,
'url' => $url, 'url' => $url,
'quantity' => $quantity > 0 ? $quantity : 0, 'quantity' => $quantity > 0 ? $quantity : 0,
@ -316,7 +310,7 @@ class RetailcrmCatalog
'productActivity' => ($available_for_order) ? 'Y' : 'N', 'productActivity' => ($available_for_order) ? 'Y' : 'N',
'name' => htmlspecialchars(strip_tags($product['name'])), 'name' => htmlspecialchars(strip_tags($product['name'])),
'productName' => htmlspecialchars(strip_tags($product['name'])), 'productName' => htmlspecialchars(strip_tags($product['name'])),
'categoryId' => array($category), 'categoryId' => $categoriesLeft,
'picture' => $pictures, 'picture' => $pictures,
'url' => $url, 'url' => $url,
'quantity' => $quantity > 0 ? $quantity : 0, 'quantity' => $quantity > 0 ? $quantity : 0,

View File

@ -69,12 +69,11 @@ class RetailcrmHistory
if (count($history) > 0) { if (count($history) > 0) {
$historyChanges = static::filterHistory($history, 'customer'); $historyChanges = static::filterHistory($history, 'customer');
$end = end($history);
Configuration::updateValue('RETAILCRM_LAST_CUSTOMERS_SYNC', $end['id']);
} }
if (count($historyChanges)) { if (count($historyChanges)) {
$end = end($historyChanges);
Configuration::updateValue('RETAILCRM_LAST_CUSTOMERS_SYNC', $end['id']);
$customersHistory = RetailcrmHistoryHelper::assemblyCustomer($historyChanges); $customersHistory = RetailcrmHistoryHelper::assemblyCustomer($historyChanges);
RetailcrmLogger::writeDebugArray(__METHOD__, array('Assembled history:', $customersHistory)); RetailcrmLogger::writeDebugArray(__METHOD__, array('Assembled history:', $customersHistory));
@ -188,7 +187,6 @@ class RetailcrmHistory
$filter = array(); $filter = array();
} }
$customerFix = array();
$orderFix = array(); $orderFix = array();
$historyChanges = array(); $historyChanges = array();
$request = new RetailcrmApiPaginatedRequest(); $request = new RetailcrmApiPaginatedRequest();
@ -203,12 +201,11 @@ class RetailcrmHistory
if (count($history) > 0) { if (count($history) > 0) {
$historyChanges = static::filterHistory($history, 'order'); $historyChanges = static::filterHistory($history, 'order');
$end = end($history);
Configuration::updateValue('RETAILCRM_LAST_ORDERS_SYNC', $end['id']);
} }
if (count($historyChanges)) { 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))); $statuses = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_STATUS'), true)));
$cartStatus = (string)(Configuration::get('RETAILCRM_API_SYNCHRONIZED_CART_STATUS')); $cartStatus = (string)(Configuration::get('RETAILCRM_API_SYNCHRONIZED_CART_STATUS'));
$deliveries = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_DELIVERY'), true))); $deliveries = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_DELIVERY'), true)));
@ -543,16 +540,30 @@ class RetailcrmHistory
$product_id = $product_id[0]; $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) { if ($product_attribute_id != 0) {
$productName = htmlspecialchars( $productName = htmlspecialchars(
strip_tags(Product::getProductName($product_id, $product_attribute_id)) strip_tags(Product::getProductName($product_id, $product_attribute_id))
); );
$combinationPrice = Combination::getPrice($product_attribute_id); $combinationPrice = Combination::getPrice($product_attribute_id);
$productPrice = $combinationPrice > 0 ? $product->getPrice() + $combinationPrice : $product->getPrice(); $productPrice = $combinationPrice > 0 ? $productPriceStatic + $combinationPrice : $productPriceStatic;
} else { } else {
$productName = htmlspecialchars(strip_tags($product->name)); $productName = htmlspecialchars(strip_tags($product->name));
$productPrice = $product->getPrice(); $productPrice = $productPriceStatic;
} }
$product_list[] = array( $product_list[] = array(
@ -676,7 +687,7 @@ class RetailcrmHistory
) )
); );
$carrier->add(false, false); $carrier->add(true, false);
/* /*
* collect order ids for single fix request * collect order ids for single fix request
*/ */
@ -689,17 +700,21 @@ class RetailcrmHistory
$orderDetail->createList($newOrder, $cart, $newOrder->current_state, $product_list); $orderDetail->createList($newOrder, $cart, $newOrder->current_state, $product_list);
if (!empty($customerFix)) {
self::$api->customersFixExternalIds($customerFix);
}
if (!empty($orderFix)) { if (!empty($orderFix)) {
self::$api->ordersFixExternalIds($orderFix); self::$api->ordersFixExternalIds($orderFix);
} }
static::updateOrderItems($newOrder->id);
//TODO //TODO
// Also update orders numbers after creating them in PrestaShop. // Also update orders numbers after creating them in PrestaShop.
// Current logic will result in autogenerated order numbers in retailCRM if // Current logic will result in autogenerated order numbers in retailCRM if
// order was placed via retailCRM interface. // order was placed via retailCRM interface.
// $upOrder = array(
// 'externalId' => $newOrder->id,
// 'number' => $newOrder->reference
// );
// self::$api->ordersEdit($upOrder);
} else { } else {
$order = $order_history; $order = $order_history;
@ -734,10 +749,12 @@ class RetailcrmHistory
->build(); ->build();
$address = $customerBuilder->getData()->getCustomerAddress(); $address = $customerBuilder->getData()->getCustomerAddress();
$address->id = $orderToUpdate->id_address_delivery; if(!is_null($address)) {
$address->id = $orderToUpdate->id_address_delivery;
$address->update(); $address->update();
$orderToUpdate->update(); $orderToUpdate->update();
}
} }
} }
@ -748,42 +765,42 @@ class RetailcrmHistory
$dtype = $order['delivery']['code']; $dtype = $order['delivery']['code'];
$dcost = !empty($order['delivery']['cost']) ? $order['delivery']['cost'] : null; $dcost = !empty($order['delivery']['cost']) ? $order['delivery']['cost'] : null;
if (isset($deliveries[$dtype]) && $deliveries[$dtype] != null) { if (
if ($deliveries[$dtype] != $orderToUpdate->id_carrier or $dcost != null) { isset($deliveries[$dtype]) && $deliveries[$dtype] != null &&
if ($dtype != null) { ($deliveries[$dtype] != $orderToUpdate->id_carrier or $dcost != null)
if (property_exists($orderToUpdate, 'id_order_carrier')) { ) {
$idOrderCarrier = $orderToUpdate->id_order_carrier; if (property_exists($orderToUpdate, 'id_order_carrier')) {
} elseif (method_exists($orderToUpdate, 'getIdOrderCarrier')) { $idOrderCarrier = $orderToUpdate->id_order_carrier;
$idOrderCarrier = $orderToUpdate->getIdOrderCarrier(); } elseif (method_exists($orderToUpdate, 'getIdOrderCarrier')) {
} $idOrderCarrier = $orderToUpdate->getIdOrderCarrier();
} else {
$orderCarrier = new OrderCarrier($idOrderCarrier); $idOrderCarrier = null;
$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();
} }
$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(); $orderHistory->save();
$orderToUpdate->current_state = $statuses[$stype];
RetailcrmLogger::writeDebug( RetailcrmLogger::writeDebug(
__METHOD__, __METHOD__,
sprintf( sprintf(
'<Order ID: %d> %s::%s', '<Order ID: %d> %s::%s',
$orderToUpdate->id, $orderToUpdate->id,
get_class($orderToUpdate), get_class($orderHistory),
'update' 'changeIdOrderState'
) )
); );
$orderToUpdate->update(); $orderHistory->changeIdOrderState($statuses[$stype], $orderToUpdate->id,true);
} }
} }
} }
@ -1302,35 +1317,7 @@ class RetailcrmHistory
); );
if ($orderDetail->save()) { if ($orderDetail->save()) {
$upOrderItems = array( static::updateOrderItems($orderDetail->id_order);
'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);
} }
unset($orderDetail); unset($orderDetail);
@ -1680,5 +1667,39 @@ class RetailcrmHistory
$object->product_name = implode('', array('\'', $name, '\'')); $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);
}
} }

View File

@ -286,11 +286,18 @@ class RetailcrmJobManager
$jobName = self::escapeJobName($job); $jobName = self::escapeJobName($job);
$jobFile = implode( $jobFile = implode(
DIRECTORY_SEPARATOR, 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)) { 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 { try {

View File

@ -158,7 +158,7 @@ class RetailcrmApiPaginatedRequest
); );
if ($response instanceof RetailcrmApiResponse && $response->offsetExists($this->dataKey)) { 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; $page = $response['pagination']['currentPage'] + 1;
} }

View File

@ -667,6 +667,9 @@ class RetailCRM extends Module
$externalId = false; $externalId = false;
if(empty($params['cart']))
return false;
$response = $this->api->ordersGet(RetailcrmTools::getCartOrderExternalId($params['cart'])); $response = $this->api->ordersGet(RetailcrmTools::getCartOrderExternalId($params['cart']));
if ($response !== false && isset($response['order'])) { if ($response !== false && isset($response['order'])) {
@ -674,9 +677,11 @@ class RetailCRM extends Module
} else { } else {
$order = Order::getByCartId($params['cart']->id); $order = Order::getByCartId($params['cart']->id);
$response = $this->api->ordersGet($order->id); if($order !== null) {
if ($response !== false && isset($response['order'])) { $response = $this->api->ordersGet($order->id);
$externalId = $order->id; if ($response !== false && isset($response['order'])) {
$externalId = $order->id;
}
} }
} }

View File

@ -16,6 +16,7 @@ class RetailcrmHistoryTest extends RetailcrmTestCase
'customersHistory', 'customersHistory',
'ordersHistory', 'ordersHistory',
'ordersGet', 'ordersGet',
'ordersEdit',
'customersGet', 'customersGet',
'customersFixExternalIds', 'customersFixExternalIds',
'ordersFixExternalIds', '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); $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); $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() private function getApiOrder()
{ {
$order = array( $order = array(