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;
/**
* @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);
}

View File

@ -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,

View File

@ -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(
'<Order ID: %d> %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);
}
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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(