diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bfbb5d3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +## v.2.2.0 +* Добавлена выгрузка истории изменений по клиентам +* Добавлена проверка имени и значения свойств товара перед отправкой заказа +* Выгрузка изменений из СРМ теперь происходит по идетификатору истории diff --git a/retailcrm/bootstrap.php b/retailcrm/bootstrap.php index 58fad09..bf5d642 100644 --- a/retailcrm/bootstrap.php +++ b/retailcrm/bootstrap.php @@ -3,7 +3,7 @@ * @author Retail Driver LCC * @copyright RetailCRM * @license GPL - * @version 2.1.1 + * @version 2.2.0 * @link https://retailcrm.ru * The MIT License (MIT) * diff --git a/retailcrm/job/export.php b/retailcrm/job/export.php index 15372df..b45b00c 100644 --- a/retailcrm/job/export.php +++ b/retailcrm/job/export.php @@ -3,7 +3,7 @@ * @author Retail Driver LCC * @copyright RetailCRM * @license GPL - * @version 2.1.3 + * @version 2.2.0 * @link https://retailcrm.ru * */ diff --git a/retailcrm/job/icml.php b/retailcrm/job/icml.php index 014e60d..680767f 100644 --- a/retailcrm/job/icml.php +++ b/retailcrm/job/icml.php @@ -3,7 +3,7 @@ * @author Retail Driver LCC * @copyright RetailCRM * @license GPL - * @version 2.1.3 + * @version 2.2.0 * @link https://retailcrm.ru * */ diff --git a/retailcrm/job/missing.php b/retailcrm/job/missing.php index 675209f..efa419a 100644 --- a/retailcrm/job/missing.php +++ b/retailcrm/job/missing.php @@ -3,7 +3,7 @@ * @author Retail Driver LCC * @copyright RetailCRM * @license GPL - * @version 2.1.3 + * @version 2.2.0 * @link https://retailcrm.ru * */ diff --git a/retailcrm/job/sync.php b/retailcrm/job/sync.php index 9751d09..1ce1dd1 100644 --- a/retailcrm/job/sync.php +++ b/retailcrm/job/sync.php @@ -3,7 +3,7 @@ * @author Retail Driver LCC * @copyright RetailCRM * @license GPL - * @version 2.1.3 + * @version 2.2.0 * @link https://retailcrm.ru * */ @@ -14,709 +14,18 @@ require(dirname(__FILE__) . '/../../../config/config.inc.php'); require(dirname(__FILE__) . '/../../../init.php'); require(dirname(__FILE__) . '/../bootstrap.php'); -$default_lang = (int) Configuration::get('PS_LANG_DEFAULT'); -$default_currency = (int) Configuration::get('PS_CURRENCY_DEFAULT'); -$default_country = (int) Configuration::get('PS_COUNTRY_DEFAULT'); - $apiUrl = Configuration::get('RETAILCRM_ADDRESS'); $apiKey = Configuration::get('RETAILCRM_API_TOKEN'); $apiVersion = Configuration::get('RETAILCRM_API_VERSION'); +RetailcrmHistory::$default_lang = (int) Configuration::get('PS_LANG_DEFAULT'); +RetailcrmHistory::$apiVersion = $apiVersion; if (!empty($apiUrl) && !empty($apiKey)) { - $api = new RetailcrmProxy($apiUrl, $apiKey, _PS_ROOT_DIR_ . '/retailcrm.log', $apiVersion); + RetailcrmHistory::$api = new RetailcrmProxy($apiUrl, $apiKey, _PS_ROOT_DIR_ . '/retailcrm.log', $apiVersion); } else { error_log('orderHistory: set api key & url first', 3, _PS_ROOT_DIR_ . '/retailcrm.log'); exit(); } -$lastSync = Configuration::get('RETAILCRM_LAST_SYNC'); -$references = new RetailcrmReferences($api); -$startFrom = ($lastSync === false) - ? date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s')))) - : $lastSync -; - -$customerFix = array(); -$orderFix = array(); -$startDate = new DateTime($startFrom); -$history = $api->ordersHistory(array( - 'startDate' => $startDate->format('Y-m-d H:i:s') -)); - -if ($history->isSuccessful() && count($history->history) > 0) { - $statuses = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_STATUS'), true))); - $deliveries = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_DELIVERY'), true))); - $payments = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_PAYMENT'), true))); - $deliveryDefault = json_decode(Configuration::get('RETAILCRM_API_DELIVERY_DEFAULT'), true); - $paymentDefault = json_decode(Configuration::get('RETAILCRM_API_PAYMENT_DEFAULT'), true); - $orders = RetailcrmHistoryHelper::assemblyOrder($history->history); - - foreach ($orders as $order_history) { - if (isset($order_history['deleted']) && $order_history['deleted'] == true) { - continue; - } - - if (!array_key_exists('externalId', $order_history)) { - $responce = $api->ordersGet($order_history['id'], 'id'); - - if ($responce->isSuccessful()) { - $order = $responce['order']; - } else { - continue; - } - - $delivery = $order['delivery']['code']; - - if (array_key_exists($delivery, $deliveries) && $deliveries[$delivery] != '') { - $deliveryType = $deliveries[$delivery]; - } - - if ($apiVersion != 5) { - $payment = $order['paymentType']; - } else { - if (isset($order['payments']) && count($order['payments']) == 1) { - $paymentCRM = end($order['payments']); - $payment = $paymentCRM['type']; - } elseif (isset($order['payments']) && count($order['payments']) > 1) { - foreach ($order['payments'] as $paymentCRM) { - if ($payment['status'] != 'paid') { - $payment = $paymentCRM['type']; - } - } - } - } - - if (array_key_exists($payment, $payments) && $payments[$payment] != '') { - if (Module::getInstanceByName($payments[$payment])) { - $paymentType = Module::getModuleName($payments[$payment]); - } else { - $paymentType = $payments[$payment]; - } - $paymentId = $payments[$payment]; - } - - $state = $order['status']; - - if (array_key_exists($state, $statuses) && $statuses[$state] != '') { - $orderStatus = $statuses[$state]; - } - if (!isset($paymentId) || !$paymentId) { - $paymentId = $paymentDefault; - } - - if (!$paymentType) { - if ($paymentDefault) { - if (Module::getInstanceByName($paymentDefault)) { - $paymentType = Module::getModuleName($paymentDefault); - } else { - $paymentType = $paymentDefault; - } - } else { - error_log( - 'orderHistory: set default payment(error in order where id = '.$order['id'].')', - 3, - _PS_ROOT_DIR_ . '/retailcrm.log' - ); - - continue; - } - } - - if (!$deliveryType) { - if ($deliveryDefault) { - $deliveryType = $deliveryDefault; - } else { - error_log( - 'orderHistory: set default delivery(error in order where id = '.$order['id'].')', - 3, - _PS_ROOT_DIR_ . '/retailcrm.log' - ); - continue; - } - } - - $customer = new Customer(); - if (!empty($order['customer']['email'])) { - $customer->getByEmail($order['customer']['email'], null, false); - } - - if (!array_key_exists('externalId', $order['customer'])) { - if (!$customer->id) { - $customer->firstname = $order['customer']['firstName']; - $customer->lastname = !empty($order['customer']['lastName']) ? $order['customer']['lastName'] : '-'; - $customer->email = Validate::isEmail($order['customer']['email']) ? - $order['customer']['email'] : - md5($order['customer']['firstName']) . '@retailcrm.ru'; - $customer->passwd = Tools::substr(str_shuffle(Tools::strtolower(sha1(rand() . time()))), 0, 5); - - $customer->add(); - } - - array_push( - $customerFix, - array( - 'id' => $order['customer']['id'], - 'externalId' => $customer->id - ) - ); - } - - $address = new Address(); - $address->id_customer = $customer->id; - $address->id_country = $default_country; - $address->lastname = $customer->lastname; - $address->firstname = $customer->firstname; - $address->alias = 'default'; - $address->postcode = $order['delivery']['address']['index']; - $address->city = !empty($order['delivery']['address']['city']) ? - $order['delivery']['address']['city'] : '-'; - $address->address1 = !empty($order['delivery']['address']['text']) ? - $order['delivery']['address']['text'] : '-'; - $address->phone = $order['phone']; - $address->add(); - - $cart = new Cart(); - $cart->id_currency = $default_currency; - $cart->id_lang = $default_lang; - $cart->id_customer = $customer->id; - $cart->id_address_delivery = (int) $address->id; - $cart->id_address_invoice = (int) $address->id; - $cart->id_carrier = (int) $deliveryType; - - $cart->add(); - - $products = array(); - - if (!empty($order['items'])) { - foreach ($order['items'] as $item) { - $productId = explode('#', $item['offer']['externalId']); - - $product = array(); - $product['id_product'] = (int) $productId[0]; - $product['id_product_attribute'] = !empty($productId[1]) ? $productId[1] : 0; - $product['quantity'] = $item['quantity']; - $product['id_address_delivery'] = (int) $address->id; - $products[] = $product; - } - } - - $cart->setWsCartRows($products); - $cart->update(); - - /* - * Create order - */ - $newOrder = new Order(); - $shops = Shop::getShops(); - $newOrder->id_shop = Context::getContext()->shop->id; - $newOrder->id_shop_group = (int)$shops[Context::getContext()->shop->id]['id_shop_group']; - $newOrder->reference = $newOrder->generateReference(); - $newOrder->id_address_delivery = (int) $address->id; - $newOrder->id_address_invoice = (int) $address->id; - $newOrder->id_cart = (int) $cart->id; - $newOrder->id_currency = $default_currency; - $newOrder->id_lang = $default_lang; - $newOrder->id_customer = (int) $customer->id; - if (isset($deliveryType)) { - $newOrder->id_carrier = (int) $deliveryType; - } - if (isset($paymentType)) { - $newOrder->payment = $paymentType; - $newOrder->module = $paymentId; - } - $newOrder->total_paid = $order['summ'] + $order['delivery']['cost']; - $newOrder->total_paid_tax_incl = $order['summ'] + $order['delivery']['cost']; - $newOrder->total_paid_tax_excl = $order['summ'] + $order['delivery']['cost']; - $newOrder->total_paid_real = $order['summ'] + $order['delivery']['cost']; - $newOrder->total_products = $order['summ']; - $newOrder->total_products_wt = $order['summ']; - $newOrder->total_shipping = $order['delivery']['cost']; - $newOrder->total_shipping_tax_incl = $order['delivery']['cost']; - $newOrder->total_shipping_tax_excl = $order['delivery']['cost']; - $newOrder->conversion_rate = 1.000000; - if (isset($orderStatus)) { - $newOrder->current_state = (int) $orderStatus; - } - if (!empty($order['delivery']['date'])) { - $newOrder->delivery_date = $order['delivery']['date']; - } - $newOrder->date_add = $order['createdAt']; - $newOrder->date_upd = $order['createdAt']; - $newOrder->invoice_date = $order['createdAt']; - $newOrder->valid = 1; - $newOrder->secure_key = md5(time()); - - if (isset($order['discount'])) { - $newOrder->total_discounts = $order['discount']; - } - - $product_list = array(); - - foreach ($order['items'] as $item) { - $product = new Product((int) $item['offer']['externalId'], false, $default_lang); - $product_id = $item['offer']['externalId']; - $product_attribute_id = 0; - if (strpos($item['offer']['externalId'], '#') !== false) { - $product_id = explode('#', $item['offer']['externalId']); - $product_attribute_id = $product_id[1]; - $product_id = $product_id[0]; - } - - 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(); - } else { - $productName = htmlspecialchars(strip_tags($product->name)); - $productPrice = $product->getPrice(); - } - - $product_list[] = array( - 'product' => $product, - 'product_attribute_id' => $product_attribute_id, - 'product_price' => $product->price, - 'product_price_inc_tax' => $productPrice, - 'product_name' => $productName, - 'quantity' => $item['quantity'] - ); - - if (isset($item['discountTotal']) && $apiVersion == 5) { - $newOrder->total_discounts += $item['discountTotal'] * $item['quantity']; - } - } - - $newOrder->add(false, false); - - foreach ($order['payments'] as $pay) { - if (!isset($pay['externalId']) && $pay['status'] == 'paid') { - $ptype = $payment['type']; - $ptypes = $references->getSystemPaymentModules(); - if ($payments[$ptype] != null) { - foreach ($ptypes as $pay) { - if ($pay['code'] == $payments[$ptype]) { - $payType = $pay['name']; - } - } - $paymentType = Module::getModuleName($payments[$ptype]); - Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'order_payment` - (`payment_method`, `order_reference` , `amount`, `date_add`) - VALUES - (\'' . $payType . '\', - \'' . $newOrder->reference . '\', - \'' . $payment['amount'] . '\', - \'' . $payment['paidAt'] . '\')'); - } - } - } - - $carrier = new OrderCarrierCore(); - $carrier->id_order = $newOrder->id; - $carrier->id_carrier = $deliveryType; - $carrier->shipping_cost_tax_excl = $order['delivery']['cost']; - $carrier->shipping_cost_tax_incl = $order['delivery']['cost']; - $carrier->date_add = $order['delivery']['date']; - $carrier->add(false, false); - - /* - * collect order ids for single fix request - */ - array_push($orderFix, array('id' => $order['id'], 'externalId' => $newOrder->id)); - - /* - * Create order details - */ - $query = 'INSERT `'._DB_PREFIX_.'order_detail` - ( - `id_order`, `id_order_invoice`, `id_shop`, `product_id`, `product_attribute_id`, - `product_name`, `product_quantity`, `product_quantity_in_stock`, `product_price`, - `product_reference`, `total_price_tax_excl`, `total_price_tax_incl`, - `unit_price_tax_excl`, `unit_price_tax_incl`, `original_product_price` - ) - - VALUES'; - - $context = new Context(); - foreach ($product_list as $product) { - $query .= '(' - .(int) $newOrder->id.', - 0, - '. Context::getContext()->shop->id.', - '.(int) $product['product']->id.', - '.$product['product_attribute_id'].', - '.implode('', array('\'', $product['product_name'], '\'')).', - '.(int) $product['quantity'].', - '.(int) $product['quantity'].', - '.$product['product_price'].', - '.implode('', array('\'', $product['product']->reference, '\'')).', - '.$product['product_price'].', - '.$product['product_price_inc_tax'].', - '.$product['product_price'].', - '.$product['product_price_inc_tax'].', - '.$product['product_price'].' - ),'; - } - - Db::getInstance()->execute(rtrim($query, ',')); - - if (!empty($customerFix)) { - $api->customersFixExternalIds($customerFix); - } - if (!empty($orderFix)) { - $api->ordersFixExternalIds($orderFix); - } - } else { - $order = $order_history; - $orderToUpdate = new Order((int) $order['externalId']); - - /* - * check delivery type - */ - if (!empty($order['delivery']['code'])) { - $dtype = $order['delivery']['code']; - $dcost = !empty($order['delivery']['cost']) ? $order['delivery']['cost'] : null; - - if ($deliveries[$dtype] != null) { - if ($deliveries[$dtype] != $orderToUpdate->id_carrier or $dcost != null) { - if ($dtype != null) { - Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'orders` - SET - `id_carrier` = \'' . $deliveries[$dtype] . '\' - WHERE - `id_order` = ' . (int)$order['externalId']); - } - - $updateCarrierFields = array(); - if ($dtype != null) { - $updateCarrierFields[] = '`id_carrier` = \'' . $deliveries[$dtype] . '\' '; - } - if ($dcost != null) { - $updateCarrierFields[] = '`shipping_cost_tax_incl` = \'' . $dcost . '\' '; - $updateCarrierFields[] = '`shipping_cost_tax_excl` = \'' . $dcost . '\' '; - } - $updateCarrierFields = implode(', ', $updateCarrierFields); - - Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'order_carrier` - SET - '.$updateCarrierFields.' - WHERE - `id_order` = \'' . $orderToUpdate->id . '\''); - } - } - } - - /* - * check payment type - */ - - if (!empty($order['paymentType']) && $apiVersion != 5) { - $ptype = $order['paymentType']; - - if ($payments[$ptype] != null) { - $paymentType = Module::getModuleName($payments[$ptype]); - if ($payments[$ptype] != $orderToUpdate->payment) { - Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'orders` - SET - `payment` = \'' . ($paymentType != null ? $paymentType : $payments[$ptype]). '\' - WHERE - `id_order` = ' . (int)$order['externalId']); - Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'order_payment` - SET - `payment_method` = \'' . $payments[$ptype] . '\' - WHERE - `order_reference` = \'' . $orderToUpdate->reference . '\''); - } - } - } elseif (!empty($order['payments']) && $apiVersion == 5) { - if ($order['payments']) { - foreach ($order['payments'] as $payment) { - if (!isset($payment['externalId']) && $payment['status'] == 'paid') { - $ptype = $payment['type']; - $ptypes = $references->getSystemPaymentModules(); - if ($payments[$ptype] != null) { - foreach ($ptypes as $pay) { - if ($pay['code'] == $payments[$ptype]) { - $payType = $pay['name']; - } - } - $paymentType = Module::getModuleName($payments[$ptype]); - Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'orders` - SET - `payment` = \'' . ($paymentType != null ? $paymentType : $payments[$ptype]). '\' - WHERE - `id_order` = ' . (int)$order['externalId']); - - Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'order_payment` - (`payment_method`, `order_reference` , `amount`, `date_add`) - VALUES - (\'' . $payType . '\', - \'' . $orderToUpdate->reference . '\', - \'' . $payment['amount'] . '\', - \'' . $payment['paidAt'] . '\')'); - } - } - } - } - } elseif (!empty($order['payments']) && $apiVersion == 5) { - if ($order['payments']) { - foreach ($order['payments'] as $payment) { - if (!isset($payment['externalId']) && $payment['status'] == 'paid') { - $ptype = $payment['type']; - $ptypes = $references->getSystemPaymentModules(); - if ($payments[$ptype] != null) { - foreach ($ptypes as $pay) { - if ($pay['code'] == $payments[$ptype]) { - $payType = $pay['name']; - } - } - $paymentType = Module::getModuleName($payments[$ptype]); - Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'orders` - SET - `payment` = \'' . ($paymentType != null ? $paymentType : $payments[$ptype]). '\' - WHERE - `id_order` = ' . (int)$order['externalId']); - - Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'order_payment` - (`payment_method`, `order_reference` , `amount`, `date_add`) - VALUES - (\'' . $payType . '\', - \'' . $orderToUpdate->reference . '\', - \'' . $payment['amount'] . '\', - \'' . $payment['paidAt'] . '\')'); - } - } - } - } - } - - /* - * Clean deleted items - */ - foreach ($order['items'] as $key => $item) { - if (isset($item['delete']) && $item['delete'] == true) { - if (strpos($item['offer']['externalId'], '#') !== false) { - $itemId = explode('#', $item['offer']['externalId']); - $product_id = $itemId[0]; - $product_attribute_id = $itemId[1]; - } else { - $product_id = $item['offer']['externalId']; - $product_attribute_id = 0; - } - - Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'order_detail` - WHERE - `id_order` = '. $orderToUpdate->id .' - AND - `product_id` = '.$product_id. ' AND `product_attribute_id` = '.$product_attribute_id); - - unset($order['items'][$key]); - $ItemDiscount = true; - } - } - - /* - * Check items quantity and discount - */ - foreach ($orderToUpdate->getProductsDetail() as $orderItem) { - foreach ($order['items'] as $key => $item) { - if (strpos($item['offer']['externalId'], '#') !== false) { - $itemId = explode('#', $item['offer']['externalId']); - $product_id = $itemId[0]; - $product_attribute_id = $itemId[1]; - } else { - $product_id = $item['offer']['externalId']; - $product_attribute_id = 0; - } - - if ($product_id == $orderItem['product_id'] && - $product_attribute_id == $orderItem['product_attribute_id']) { - // discount - if (isset($item['discount']) || - isset($item['discountPercent']) || - isset($item['discountTotal'])) { - - $product = new Product((int) $product_id, false, $default_lang); - $tax = new TaxCore($product->id_tax_rules_group); - - if ($product_attribute_id != 0) { - $prodPrice = Combination::getPrice($product_attribute_id); - $prodPrice = $prodPrice > 0 ? $prodPrice : $product->price; - } else { - $prodPrice = $product->price; - } - - $prodPrice = $prodPrice + $prodPrice / 100 * $tax->rate; - - $productPrice = $prodPrice - $item['discount']; - $productPrice = $productPrice - ($prodPrice / 100 * $item['discountPercent']); - $productPrice = $prodPrice - $item['discountTotal']; - - $productPrice = round($productPrice, 2); - - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'order_detail` - SET - `unit_price_tax_incl` = '.$productPrice.' - WHERE - `id_order_detail` = '.$orderItem['id_order_detail']); - } - - // quantity - if (isset($item['quantity']) && $item['quantity'] != $orderItem['product_quantity']) { - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'order_detail` - SET - `product_quantity` = '.$item['quantity'].', - `product_quantity_in_stock` = '.$item['quantity'].' - WHERE - `id_order_detail` = '.$orderItem['id_order_detail']); - } - - $ItemDiscount = true; - unset($order['items'][$key]); - } - } - } - - /* - * Check new items - */ - if (!empty($order['items'])) { - $query = 'INSERT `'._DB_PREFIX_.'order_detail` - ( - `id_order`, `id_order_invoice`, `id_shop`, `product_id`, `product_attribute_id`, - `product_name`, `product_quantity`, `product_quantity_in_stock`, `product_price`, - `product_reference`, `total_price_tax_excl`, `total_price_tax_incl`, - `unit_price_tax_excl`, `unit_price_tax_incl`, `original_product_price` - ) - - VALUES'; - - foreach ($order['items'] as $key => $newItem) { - $product_id = $newItem['offer']['externalId']; - $product_attribute_id = 0; - if (strpos($product_id, '#') !== false) { - $product_id = explode('#', $product_id); - - $product_attribute_id = $product_id[1]; - $product_id = $product_id[0]; - } - - $product = new Product((int) $product_id, false, $default_lang); - $tax = new TaxCore($product->id_tax_rules_group); - - if ($product_attribute_id != 0) { - $productName = htmlspecialchars( - strip_tags(Product::getProductName($product_id, $product_attribute_id)) - ); - $productPrice = Combination::getPrice($product_attribute_id); - $productPrice = $productPrice > 0 ? $productPrice : $product->price; - } else { - $productName = htmlspecialchars(strip_tags($product->name)); - $productPrice = $product->price; - } - - // discount - if ($newItem['discount'] || $newItem['discountPercent']|| $newItem['discountTotal']) { - $productPrice = $productPrice - $newItem['discount']; - $productPrice = $productPrice - $newItem['discountTotal']; - $productPrice = $productPrice - ($prodPrice / 100 * $newItem['discountPercent']); - $ItemDiscount = true; - } - - $query .= '(' - .(int) $orderToUpdate->id.', - 0, - '. Context::getContext()->shop->id.', - '.(int) $product_id.', - '.(int) $product_attribute_id.', - '.implode('', array('\'', $productName, '\'')).', - '.(int) $newItem['quantity'].', - '.(int) $newItem['quantity'].', - '.$productPrice.', - '.implode('', array('\'', $product->reference, '\'')).', - '.$productPrice * $newItem['quantity'].', - '.($productPrice + $productPrice / 100 * $tax->rate) * $newItem['quantity'].', - '.$productPrice.', - '.($productPrice + $productPrice / 100 * $tax->rate).', - '.$productPrice.' - ),'; - - unset($order['items'][$key]); - } - - Db::getInstance()->execute(rtrim($query, ',')); - } - - /* - * Fix prices & discounts - * Discounts only for whole order - */ - if (isset($order['discount']) || - isset($order['discountPercent']) || - isset($order['delivery']['cost']) || - isset($order['discountTotal']) || - $ItemDiscount) { - $infoOrd = $api->ordersGet($order['externalId']); - $infoOrder = $infoOrd->order; - $orderTotalProducts = $infoOrder['summ']; - $totalPaid = $infoOrder['totalSumm']; - $deliveryCost = $infoOrder['delivery']['cost']; - $totalDiscount = $deliveryCost + $orderTotalProducts - $totalPaid; - - $orderCartRules = $orderToUpdate->getCartRules(); - foreach ($orderCartRules as $valCartRules) { - $order_cart_rule = new OrderCartRule($valCartRules['id_order_cart_rule']); - $order_cart_rule->delete(); - } - $orderToUpdate->update(); - - Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'orders` - SET - `total_discounts` = '.$totalDiscount.', - `total_discounts_tax_incl` = '.$totalDiscount.', - `total_discounts_tax_excl` = '.$totalDiscount.', - `total_shipping` = '.$deliveryCost.', - `total_shipping_tax_incl` = '.$deliveryCost.', - `total_shipping_tax_excl` = '.$deliveryCost.', - `total_paid` = '.$totalPaid.', - `total_paid_tax_incl` = '.$totalPaid.', - `total_paid_tax_excl` = '.$totalPaid.', - `total_products_wt` = '.$orderTotalProducts.' - WHERE `id_order` = '.(int) $order['externalId']); - - unset($ItemDiscount); - } - - /* - * check status - */ - if (!empty($order['status'])) { - $stype = $order['status']; - - if ($statuses[$stype] != null) { - if ($statuses[$stype] != $orderToUpdate->current_state) { - Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'order_history` - (`id_employee`, `id_order`, `id_order_state`, `date_add`) - VALUES - (0, ' . $orderToUpdate->id . ', - ' . $statuses[$stype] . ', - "' . date('Y-m-d H:i:s') . '")'); - - Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'orders` - SET - `current_state` = \'' . $statuses[$stype] . '\' - WHERE - `id_order` = ' . (int)$order['externalId']); - } - } - } - } - } - /* - * Update last sync timestamp - */ - Configuration::updateValue('RETAILCRM_LAST_SYNC', $history->generatedAt); -} else { - return 'Nothing to sync'; -} +RetailcrmHistory::customersHistory(); +RetailcrmHistory::ordersHistory(); diff --git a/retailcrm/lib/RetailcrmHistory.php b/retailcrm/lib/RetailcrmHistory.php new file mode 100644 index 0000000..4b640fa --- /dev/null +++ b/retailcrm/lib/RetailcrmHistory.php @@ -0,0 +1,815 @@ + date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s'))))) + : array('sinceId' => $lastSync); + + $history = self::$api->customersHistory($filter); + + if ($history->isSuccessful() && count($history->history)) { + $historyChanges = $history->history; + $end = end($historyChanges); + $sinceid = $end['id']; + + $customersHistory = RetailcrmHistoryHelper::assemblyCustomer($historyChanges); + + foreach ($customersHistory as $customerHistory) { + if (isset($customerHistory['externalId'])) { + $customer = new Customer($customerHistory['externalId']); + + if (isset($customerHistory['firstName'])) { + $customer->firstname = $customerHistory['firstName']; + } + + if (isset($customerHistory['lastName'])) { + $customer->lastname = $customerHistory['lastName']; + } + + if (isset($customerHistory['birthday'])) { + $customer->birthday = $customerHistory['birthday']; + } + + if (isset($customerHistory['email']) && Validate::isEmail($customerHistory['email'])) { + $customer->email = $customerHistory['email']; + } + + $customer->update(); + } else { + $customer = new Customer(); + + $customer->firstname = $customerHistory['firstName']; + $customer->lastname = isset($customerHistory['lastName']) ? $customerHistory['lastName'] : '--'; + $customer->id_lang = self::$default_lang; + + if (isset($customerHistory['birthday'])) { + $customer->birthday = $customerHistory['birthday']; + } + + if (isset($customerHistory['sex'])) { + $customer->id_gender = $customerHistory['sex'] == 'male' ? 1 : 2; + } + + if (isset($customerHistory['email']) && Validate::isEmail($customerHistory['email'])) { + $customer->email = $customerHistory['email']; + } else { + $customer->email = md5($customerHistory['firstName']) . '@retailcrm.ru'; + } + + $customer->passwd = Tools::substr(str_shuffle(Tools::strtolower(sha1(rand() . time()))), 0, 5); + + $customer->add(); + + if (isset($customerHistory['address'])) { + $customerAddress = new Address(); + $customerAddress->id_customer = $customer->id; + $customerAddress->alias = 'default'; + $customerAddress->lastname = $customer->lastname; + $customerAddress->firstname = $customer->firstname; + + if (isset($customerHistory['address']['countryIso'])) { + $customerAddress->id_country = Country::getByIso($customerHistory['address']['countryIso']); + } + + if (isset($customerHistory['address']['region'])) { + $customerAddress->id_state = State::getIdByName($customerHistory['address']['region']); + } + + $customerAddress->city = isset($customerHistory['address']['city']) ? $customerHistory['address']['city'] : '--'; + + $customerAddress->address1 = isset($customerHistory['address']['text']) ? $customerHistory['address']['text'] : '--'; + + if (isset($customerHistory['phones'])) { + $phone = reset($customerHistory['phones']); + $customerAddress->phone = $phone['number']; + } + + if (isset($customerHistory['address']['index'])) { + $customerAddress->postcode = $customerHistory['address']['index']; + } + + $customerAddress->add(); + } + + $customerFix[] = array( + 'id' => $customerHistory['id'], + 'externalId' => $customer->id + ); + } + } + + if (!empty($customerFix)) { + self::$api->customersFixExternalIds($customerFix); + } + + /* + * Update last sync id + */ + Configuration::updateValue('RETAILCRM_LAST_CUSTOMERS_SYNC', $sinceid); + } else { + return 'Nothing to sync'; + } + } + + /** + * Get orders history + * + * @return string + */ + public static function ordersHistory() + { + $default_currency = (int) Configuration::get('PS_CURRENCY_DEFAULT'); + $default_country = (int) Configuration::get('PS_COUNTRY_DEFAULT'); + + $lastSync = Configuration::get('RETAILCRM_LAST_ORDERS_SYNC'); + $lastDate = Configuration::get('RETAILCRM_LAST_SYNC'); + $references = new RetailcrmReferences(self::$api); + + if ($lastSync === false && $lastDate === false) { + $filter = array('startDate' => date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s'))))); + } elseif ($lastSync === false && $lastDate !== false) { + $filter = array('startDate' => $lastDate); + } elseif ($lastSync !== false) { + $filter = array('sinceId' => $lastSync); + } + + $customerFix = array(); + $orderFix = array(); + $history = self::$api->ordersHistory($filter); + + if ($history->isSuccessful() && count($history->history) > 0) { + $historyChanges = $history->history; + $end = end($historyChanges); + $sinceId = $end['id']; + + $statuses = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_STATUS'), true))); + $deliveries = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_DELIVERY'), true))); + $payments = array_flip(array_filter(json_decode(Configuration::get('RETAILCRM_API_PAYMENT'), true))); + $deliveryDefault = json_decode(Configuration::get('RETAILCRM_API_DELIVERY_DEFAULT'), true); + $paymentDefault = json_decode(Configuration::get('RETAILCRM_API_PAYMENT_DEFAULT'), true); + $orders = RetailcrmHistoryHelper::assemblyOrder($historyChanges); + + foreach ($orders as $order_history) { + if (isset($order_history['deleted']) && $order_history['deleted'] == true) { + continue; + } + + if (!array_key_exists('externalId', $order_history)) { + $responce = self::$api->ordersGet($order_history['id'], 'id'); + + if ($responce->isSuccessful()) { + $order = $responce['order']; + } else { + continue; + } + + $delivery = $order['delivery']['code']; + + if (array_key_exists($delivery, $deliveries) && $deliveries[$delivery] != '') { + $deliveryType = $deliveries[$delivery]; + } + + if (self::$apiVersion != 5) { + $payment = $order['paymentType']; + } else { + if (isset($order['payments']) && count($order['payments']) == 1) { + $paymentCRM = end($order['payments']); + $payment = $paymentCRM['type']; + } elseif (isset($order['payments']) && count($order['payments']) > 1) { + foreach ($order['payments'] as $paymentCRM) { + if ($payment['status'] != 'paid') { + $payment = $paymentCRM['type']; + } + } + } + } + + if (array_key_exists($payment, $payments) && $payments[$payment] != '') { + if (Module::getInstanceByName($payments[$payment])) { + $paymentType = Module::getModuleName($payments[$payment]); + } else { + $paymentType = $payments[$payment]; + } + $paymentId = $payments[$payment]; + } + + $state = $order['status']; + + if (array_key_exists($state, $statuses) && $statuses[$state] != '') { + $orderStatus = $statuses[$state]; + } + if (!isset($paymentId) || !$paymentId) { + $paymentId = $paymentDefault; + } + + if (!$paymentType) { + if ($paymentDefault) { + if (Module::getInstanceByName($paymentDefault)) { + $paymentType = Module::getModuleName($paymentDefault); + } else { + $paymentType = $paymentDefault; + } + } else { + error_log( + 'orderHistory: set default payment(error in order where id = '.$order['id'].')', + 3, + _PS_ROOT_DIR_ . '/retailcrm.log' + ); + + continue; + } + } + + if (!$deliveryType) { + if ($deliveryDefault) { + $deliveryType = $deliveryDefault; + } else { + error_log( + 'orderHistory: set default delivery(error in order where id = '.$order['id'].')', + 3, + _PS_ROOT_DIR_ . '/retailcrm.log' + ); + continue; + } + } + + if (array_key_exists('externalId', $order['customer'])) { + $customerId = Customer::customerIdExistsStatic($order['customer']['externalId']); + } + + if (!array_key_exists('externalId', $order['customer']) + || (isset($customerId) && $customerId == 0) + ) { + $customer = new Customer(); + $customer->firstname = $order['customer']['firstName']; + $customer->lastname = !empty($order['customer']['lastName']) ? $order['customer']['lastName'] : '--'; + $customer->email = Validate::isEmail($order['customer']['email']) ? + $order['customer']['email'] : + md5($order['customer']['firstName']) . '@retailcrm.ru'; + $customer->passwd = Tools::substr(str_shuffle(Tools::strtolower(sha1(rand() . time()))), 0, 5); + + $customer->add(); + + array_push( + $customerFix, + array( + 'id' => $order['customer']['id'], + 'externalId' => $customer->id + ) + ); + } else { + $customer = new Customer($customerId); + } + + $address = new Address(); + $address->id_customer = $customer->id; + $address->id_country = $default_country; + $address->lastname = $customer->lastname; + $address->firstname = $customer->firstname; + $address->alias = 'default'; + $address->postcode = isset($order['delivery']['address']['index']) ? $order['delivery']['address']['index'] : '--'; + $address->city = !empty($order['delivery']['address']['city']) ? + $order['delivery']['address']['city'] : '--'; + $address->address1 = !empty($order['delivery']['address']['text']) ? + $order['delivery']['address']['text'] : '--'; + $address->phone = isset($order['phone']) ? $order['phone'] : ''; + $address->add(); + + $cart = new Cart(); + $cart->id_currency = $default_currency; + $cart->id_lang = self::$default_lang; + $cart->id_customer = $customer->id; + $cart->id_address_delivery = (int) $address->id; + $cart->id_address_invoice = (int) $address->id; + $cart->id_carrier = (int) $deliveryType; + + $cart->add(); + + $products = array(); + + if (!empty($order['items'])) { + foreach ($order['items'] as $item) { + $productId = explode('#', $item['offer']['externalId']); + + $product = array(); + $product['id_product'] = (int) $productId[0]; + $product['id_product_attribute'] = !empty($productId[1]) ? $productId[1] : 0; + $product['quantity'] = $item['quantity']; + $product['id_address_delivery'] = (int) $address->id; + $products[] = $product; + } + } + + $cart->setWsCartRows($products); + $cart->update(); + + /* + * Create order + */ + $newOrder = new Order(); + $shops = Shop::getShops(); + $newOrder->id_shop = Context::getContext()->shop->id; + $newOrder->id_shop_group = (int)$shops[Context::getContext()->shop->id]['id_shop_group']; + $newOrder->reference = $newOrder->generateReference(); + $newOrder->id_address_delivery = (int) $address->id; + $newOrder->id_address_invoice = (int) $address->id; + $newOrder->id_cart = (int) $cart->id; + $newOrder->id_currency = $default_currency; + $newOrder->id_lang = self::$default_lang; + $newOrder->id_customer = (int) $customer->id; + if (isset($deliveryType)) { + $newOrder->id_carrier = (int) $deliveryType; + } + if (isset($paymentType)) { + $newOrder->payment = $paymentType; + $newOrder->module = $paymentId; + } + $newOrder->total_paid = $order['summ'] + $order['delivery']['cost']; + $newOrder->total_paid_tax_incl = $order['summ'] + $order['delivery']['cost']; + $newOrder->total_paid_tax_excl = $order['summ'] + $order['delivery']['cost']; + $newOrder->total_paid_real = $order['summ'] + $order['delivery']['cost']; + $newOrder->total_products = $order['summ']; + $newOrder->total_products_wt = $order['summ']; + $newOrder->total_shipping = $order['delivery']['cost']; + $newOrder->total_shipping_tax_incl = $order['delivery']['cost']; + $newOrder->total_shipping_tax_excl = $order['delivery']['cost']; + $newOrder->conversion_rate = 1.000000; + if (isset($orderStatus)) { + $newOrder->current_state = (int) $orderStatus; + } + if (!empty($order['delivery']['date'])) { + $newOrder->delivery_date = $order['delivery']['date']; + } + $newOrder->date_add = $order['createdAt']; + $newOrder->date_upd = $order['createdAt']; + $newOrder->invoice_date = $order['createdAt']; + $newOrder->valid = 1; + $newOrder->secure_key = md5(time()); + + if (isset($order['discount'])) { + $newOrder->total_discounts = $order['discount']; + } + + $product_list = array(); + + foreach ($order['items'] as $item) { + $product = new Product((int) $item['offer']['externalId'], false, self::$default_lang); + $product_id = $item['offer']['externalId']; + $product_attribute_id = 0; + if (strpos($item['offer']['externalId'], '#') !== false) { + $product_id = explode('#', $item['offer']['externalId']); + $product_attribute_id = $product_id[1]; + $product_id = $product_id[0]; + } + + 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(); + } else { + $productName = htmlspecialchars(strip_tags($product->name)); + $productPrice = $product->getPrice(); + } + + $product_list[] = array( + 'product' => $product, + 'product_attribute_id' => $product_attribute_id, + 'product_price' => $product->price, + 'product_price_inc_tax' => $productPrice, + 'product_name' => $productName, + 'quantity' => $item['quantity'] + ); + + if (isset($item['discountTotal']) && self::$apiVersion == 5) { + $newOrder->total_discounts += $item['discountTotal'] * $item['quantity']; + } + } + + $newOrder->add(false, false); + + if (isset($order['payments']) && !empty($order['payments'])) { + foreach ($order['payments'] as $pay) { + if (!isset($pay['externalId']) && $pay['status'] == 'paid') { + $ptype = $payment['type']; + $ptypes = $references->getSystemPaymentModules(); + if ($payments[$ptype] != null) { + foreach ($ptypes as $pay) { + if ($pay['code'] == $payments[$ptype]) { + $payType = $pay['name']; + } + } + $paymentType = Module::getModuleName($payments[$ptype]); + Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'order_payment` + (`payment_method`, `order_reference` , `amount`, `date_add`) + VALUES + (\'' . $payType . '\', + \'' . $newOrder->reference . '\', + \'' . $payment['amount'] . '\', + \'' . $payment['paidAt'] . '\')'); + } + } + } + } + + $carrier = new OrderCarrierCore(); + $carrier->id_order = $newOrder->id; + $carrier->id_carrier = $deliveryType; + $carrier->shipping_cost_tax_excl = $order['delivery']['cost']; + $carrier->shipping_cost_tax_incl = $order['delivery']['cost']; + $carrier->date_add = isset($order['delivery']['date']) ? $order['delivery']['date'] : ''; + $carrier->add(false, false); + + /* + * collect order ids for single fix request + */ + array_push($orderFix, array('id' => $order['id'], 'externalId' => $newOrder->id)); + + /* + * Create order details + */ + $query = 'INSERT `'._DB_PREFIX_.'order_detail` + ( + `id_order`, `id_order_invoice`, `id_shop`, `product_id`, `product_attribute_id`, + `product_name`, `product_quantity`, `product_quantity_in_stock`, `product_price`, + `product_reference`, `total_price_tax_excl`, `total_price_tax_incl`, + `unit_price_tax_excl`, `unit_price_tax_incl`, `original_product_price` + ) + + VALUES'; + + $context = new Context(); + foreach ($product_list as $product) { + $query .= '(' + .(int) $newOrder->id.', + 0, + '. Context::getContext()->shop->id.', + '.(int) $product['product']->id.', + '.$product['product_attribute_id'].', + '.implode('', array('\'', $product['product_name'], '\'')).', + '.(int) $product['quantity'].', + '.(int) $product['quantity'].', + '.$product['product_price'].', + '.implode('', array('\'', $product['product']->reference, '\'')).', + '.$product['product_price'].', + '.$product['product_price_inc_tax'].', + '.$product['product_price'].', + '.$product['product_price_inc_tax'].', + '.$product['product_price'].' + ),'; + } + + Db::getInstance()->execute(rtrim($query, ',')); + + if (!empty($customerFix)) { + self::$api->customersFixExternalIds($customerFix); + } + if (!empty($orderFix)) { + self::$api->ordersFixExternalIds($orderFix); + } + } else { + $order = $order_history; + $orderToUpdate = new Order((int) $order['externalId']); + + /* + * check delivery type + */ + if (!empty($order['delivery']['code'])) { + $dtype = $order['delivery']['code']; + $dcost = !empty($order['delivery']['cost']) ? $order['delivery']['cost'] : null; + + if ($deliveries[$dtype] != null) { + if ($deliveries[$dtype] != $orderToUpdate->id_carrier or $dcost != null) { + if ($dtype != null) { + Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'orders` + SET + `id_carrier` = \'' . $deliveries[$dtype] . '\' + WHERE + `id_order` = ' . (int)$order['externalId']); + } + + $updateCarrierFields = array(); + if ($dtype != null) { + $updateCarrierFields[] = '`id_carrier` = \'' . $deliveries[$dtype] . '\' '; + } + if ($dcost != null) { + $updateCarrierFields[] = '`shipping_cost_tax_incl` = \'' . $dcost . '\' '; + $updateCarrierFields[] = '`shipping_cost_tax_excl` = \'' . $dcost . '\' '; + } + $updateCarrierFields = implode(', ', $updateCarrierFields); + + Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'order_carrier` + SET + '.$updateCarrierFields.' + WHERE + `id_order` = \'' . $orderToUpdate->id . '\''); + } + } + } + + /* + * check payment type + */ + + if (!empty($order['paymentType']) && self::$apiVersion != 5) { + $ptype = $order['paymentType']; + + if ($payments[$ptype] != null) { + $paymentType = Module::getModuleName($payments[$ptype]); + if ($payments[$ptype] != $orderToUpdate->payment) { + Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'orders` + SET + `payment` = \'' . ($paymentType != null ? $paymentType : $payments[$ptype]). '\' + WHERE + `id_order` = ' . (int)$order['externalId']); + Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'order_payment` + SET + `payment_method` = \'' . $payments[$ptype] . '\' + WHERE + `order_reference` = \'' . $orderToUpdate->reference . '\''); + } + } + } elseif (!empty($order['payments']) && self::$apiVersion == 5) { + foreach ($order['payments'] as $payment) { + if (!isset($payment['externalId']) + && isset($payment['status']) + && $payment['status'] == 'paid' + ) { + $ptype = $payment['type']; + $ptypes = $references->getSystemPaymentModules(); + if ($payments[$ptype] != null) { + foreach ($ptypes as $pay) { + if ($pay['code'] == $payments[$ptype]) { + $payType = $pay['name']; + } + } + $paymentType = Module::getModuleName($payments[$ptype]); + Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'orders` + SET + `payment` = \'' . ($paymentType != null ? $paymentType : $payments[$ptype]). '\' + WHERE + `id_order` = ' . (int)$order['externalId']); + + Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'order_payment` + (`payment_method`, `order_reference` , `amount`, `date_add`) + VALUES + (\'' . $payType . '\', + \'' . $orderToUpdate->reference . '\', + \'' . $payment['amount'] . '\', + \'' . $payment['paidAt'] . '\')'); + } + } + } + } + + /* + * Clean deleted items + */ + foreach ($order['items'] as $key => $item) { + if (isset($item['delete']) && $item['delete'] == true) { + if (strpos($item['offer']['externalId'], '#') !== false) { + $itemId = explode('#', $item['offer']['externalId']); + $product_id = $itemId[0]; + $product_attribute_id = $itemId[1]; + } else { + $product_id = $item['offer']['externalId']; + $product_attribute_id = 0; + } + + Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'order_detail` + WHERE + `id_order` = '. $orderToUpdate->id .' + AND + `product_id` = '.$product_id. ' AND `product_attribute_id` = '.$product_attribute_id); + + unset($order['items'][$key]); + $ItemDiscount = true; + } + } + + /* + * Check items quantity and discount + */ + foreach ($orderToUpdate->getProductsDetail() as $orderItem) { + foreach ($order['items'] as $key => $item) { + if (strpos($item['offer']['externalId'], '#') !== false) { + $itemId = explode('#', $item['offer']['externalId']); + $product_id = $itemId[0]; + $product_attribute_id = $itemId[1]; + } else { + $product_id = $item['offer']['externalId']; + $product_attribute_id = 0; + } + + if ($product_id == $orderItem['product_id'] && + $product_attribute_id == $orderItem['product_attribute_id']) { + + $product = new Product((int) $product_id, false, self::$default_lang); + $tax = new TaxCore($product->id_tax_rules_group); + + if ($product_attribute_id != 0) { + $prodPrice = Combination::getPrice($product_attribute_id); + $prodPrice = $prodPrice > 0 ? $prodPrice : $product->price; + } else { + $prodPrice = $product->price; + } + + $prodPrice = $prodPrice + $prodPrice / 100 * $tax->rate; + + // discount + if (self::$apiVersion == 5) { + $productPrice = $prodPrice - $item['discountTotal']; + } else { + $productPrice = $prodPrice - $item['discount']; + + if ($item['discountPercent'] > 0) { + $productPrice = $productPrice - ($prodPrice / 100 * $item['discountPercent']); + } + } + + $productPrice = round($productPrice, 2); + + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'order_detail` + SET + `unit_price_tax_incl` = '.$productPrice.' + WHERE + `id_order_detail` = '.$orderItem['id_order_detail']); + + // quantity + if (isset($item['quantity']) && $item['quantity'] != $orderItem['product_quantity']) { + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'order_detail` + SET + `product_quantity` = '.$item['quantity'].', + `product_quantity_in_stock` = '.$item['quantity'].' + WHERE + `id_order_detail` = '.$orderItem['id_order_detail']); + } + + $ItemDiscount = true; + unset($order['items'][$key]); + } + } + } + + /* + * Check new items + */ + if (!empty($order['items'])) { + $query = 'INSERT `'._DB_PREFIX_.'order_detail` + ( + `id_order`, `id_order_invoice`, `id_shop`, `product_id`, `product_attribute_id`, + `product_name`, `product_quantity`, `product_quantity_in_stock`, `product_price`, + `product_reference`, `total_price_tax_excl`, `total_price_tax_incl`, + `unit_price_tax_excl`, `unit_price_tax_incl`, `original_product_price` + ) + + VALUES'; + + foreach ($order['items'] as $key => $newItem) { + $product_id = $newItem['offer']['externalId']; + $product_attribute_id = 0; + if (strpos($product_id, '#') !== false) { + $product_id = explode('#', $product_id); + + $product_attribute_id = $product_id[1]; + $product_id = $product_id[0]; + } + + $product = new Product((int) $product_id, false, self::$default_lang); + $tax = new TaxCore($product->id_tax_rules_group); + + if ($product_attribute_id != 0) { + $productName = htmlspecialchars( + strip_tags(Product::getProductName($product_id, $product_attribute_id)) + ); + $productPrice = Combination::getPrice($product_attribute_id); + $productPrice = $productPrice > 0 ? $productPrice : $product->price; + } else { + $productName = htmlspecialchars(strip_tags($product->name)); + $productPrice = $product->price; + } + + // discount + if ($newItem['discount'] || $newItem['discountPercent']|| $newItem['discountTotal']) { + $productPrice = $productPrice - $newItem['discount']; + $productPrice = $productPrice - $newItem['discountTotal']; + $productPrice = $productPrice - ($prodPrice / 100 * $newItem['discountPercent']); + $ItemDiscount = true; + } + + $query .= '(' + .(int) $orderToUpdate->id.', + 0, + '. Context::getContext()->shop->id.', + '.(int) $product_id.', + '.(int) $product_attribute_id.', + '.implode('', array('\'', $productName, '\'')).', + '.(int) $newItem['quantity'].', + '.(int) $newItem['quantity'].', + '.$productPrice.', + '.implode('', array('\'', $product->reference, '\'')).', + '.$productPrice * $newItem['quantity'].', + '.($productPrice + $productPrice / 100 * $tax->rate) * $newItem['quantity'].', + '.$productPrice.', + '.($productPrice + $productPrice / 100 * $tax->rate).', + '.$productPrice.' + ),'; + + unset($order['items'][$key]); + } + + Db::getInstance()->execute(rtrim($query, ',')); + } + + /* + * Fix prices & discounts + * Discounts only for whole order + */ + if (isset($order['discount']) || + isset($order['discountPercent']) || + isset($order['delivery']['cost']) || + isset($order['discountTotal']) || + $ItemDiscount) { + $infoOrd = self::$api->ordersGet($order['externalId']); + $infoOrder = $infoOrd->order; + $orderTotalProducts = $infoOrder['summ']; + $totalPaid = $infoOrder['totalSumm']; + $deliveryCost = $infoOrder['delivery']['cost']; + $totalDiscount = $deliveryCost + $orderTotalProducts - $totalPaid; + + $orderCartRules = $orderToUpdate->getCartRules(); + foreach ($orderCartRules as $valCartRules) { + $order_cart_rule = new OrderCartRule($valCartRules['id_order_cart_rule']); + $order_cart_rule->delete(); + } + $orderToUpdate->update(); + + Db::getInstance()->execute('UPDATE `'._DB_PREFIX_.'orders` + SET + `total_discounts` = '.$totalDiscount.', + `total_discounts_tax_incl` = '.$totalDiscount.', + `total_discounts_tax_excl` = '.$totalDiscount.', + `total_shipping` = '.$deliveryCost.', + `total_shipping_tax_incl` = '.$deliveryCost.', + `total_shipping_tax_excl` = '.$deliveryCost.', + `total_paid` = '.$totalPaid.', + `total_paid_tax_incl` = '.$totalPaid.', + `total_paid_tax_excl` = '.$totalPaid.', + `total_products_wt` = '.$orderTotalProducts.' + WHERE `id_order` = '.(int) $order['externalId']); + + unset($ItemDiscount); + } + + /** + * check status + */ + if (!empty($order['status'])) { + $stype = $order['status']; + + if ($statuses[$stype] != null) { + if ($statuses[$stype] != $orderToUpdate->current_state) { + Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'order_history` + (`id_employee`, `id_order`, `id_order_state`, `date_add`) + VALUES + (0, ' . $orderToUpdate->id . ', + ' . $statuses[$stype] . ', + "' . date('Y-m-d H:i:s') . '")'); + + Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'orders` + SET + `current_state` = \'' . $statuses[$stype] . '\' + WHERE + `id_order` = ' . (int)$order['externalId']); + } + } + } + } + } + /* + * Update last sync timestamp + */ + Configuration::updateValue('RETAILCRM_LAST_ORDERS_SYNC', $sinceId); + } else { + return 'Nothing to sync'; + } + } +} \ No newline at end of file diff --git a/retailcrm/lib/RetailcrmHistoryHelper.php b/retailcrm/lib/RetailcrmHistoryHelper.php index 8882f85..b31a958 100644 --- a/retailcrm/lib/RetailcrmHistoryHelper.php +++ b/retailcrm/lib/RetailcrmHistoryHelper.php @@ -12,10 +12,10 @@ class RetailcrmHistoryHelper { $orders = array(); foreach ($orderHistory as $change) { $change['order'] = self::removeEmpty($change['order']); - if($change['order']['items']) { + if (isset($change['order']['items']) && $change['order']['items']) { $items = array(); foreach($change['order']['items'] as $item) { - if(isset($change['created'])) { + if (isset($change['created'])) { $item['create'] = 1; } $items[$item['id']] = $item; @@ -23,70 +23,84 @@ class RetailcrmHistoryHelper { $change['order']['items'] = $items; } - if($change['order']['contragent']['contragentType']) { + if (isset($change['order']['contragent']['contragentType'])) { $change['order']['contragentType'] = $change['order']['contragent']['contragentType']; unset($change['order']['contragent']); } - if($orders[$change['order']['id']]) { + if (isset($orders[$change['order']['id']])) { $orders[$change['order']['id']] = array_merge($orders[$change['order']['id']], $change['order']); } else { $orders[$change['order']['id']] = $change['order']; } - if($change['payment']) { - if($orders[$change['order']['id']]['payments'][$change['payment']['id']]) { + if (isset($change['payment'])) { + if (isset($orders[$change['order']['id']]['payments'][$change['payment']['id']])) { $orders[$change['order']['id']]['payments'][$change['payment']['id']] = array_merge($orders[$change['order']['id']]['payments'][$change['payment']['id']], $change['payment']); } else { $orders[$change['order']['id']]['payments'][$change['payment']['id']] = $change['payment']; } - if($change['oldValue'] == null && $change['field'] == 'payments') { + if ($change['oldValue'] == null && $change['field'] == 'payments') { $orders[$change['order']['id']]['payments'][$change['payment']['id']]['create'] = true; } - if($change['newValue'] == null && $change['field'] == 'payments') { + if ($change['newValue'] == null && $change['field'] == 'payments') { $orders[$change['order']['id']]['payments'][$change['payment']['id']]['delete'] = true; } - if(!$orders[$change['order']['id']]['payments'][$change['payment']['id']]['create'] && $fields['payment'][$change['field']]) { + if (!$orders[$change['order']['id']]['payments'][$change['payment']['id']]['create'] && $fields['payment'][$change['field']]) { $orders[$change['order']['id']]['payments'][$change['payment']['id']][$fields['payment'][$change['field']]] = $change['newValue']; } } - if($change['item']) { - if($orders[$change['order']['id']]['items'][$change['item']['id']]) { + if (isset($change['item'])) { + if (isset($orders[$change['order']['id']]['items'][$change['item']['id']])) { $orders[$change['order']['id']]['items'][$change['item']['id']] = array_merge($orders[$change['order']['id']]['items'][$change['item']['id']], $change['item']); } else { $orders[$change['order']['id']]['items'][$change['item']['id']] = $change['item']; } - if(empty($change['oldValue']) && $change['field'] == 'order_product') { + if (empty($change['oldValue']) && $change['field'] == 'order_product') { $orders[$change['order']['id']]['items'][$change['item']['id']]['create'] = true; } - if(empty($change['newValue']) && $change['field'] == 'order_product') { + if (empty($change['newValue']) && $change['field'] == 'order_product') { $orders[$change['order']['id']]['items'][$change['item']['id']]['delete'] = true; } - if(!$orders[$change['order']['id']]['items'][$change['item']['id']]['create'] && $fields['item'][$change['field']]) { + if (!$orders[$change['order']['id']]['items'][$change['item']['id']]['create'] && $fields['item'][$change['field']]) { $orders[$change['order']['id']]['items'][$change['item']['id']][$fields['item'][$change['field']]] = $change['newValue']; } } else { - if($fields['delivery'][$change['field']] == 'service') { + if (isset($fields['delivery'][$change['field']]) + && $fields['delivery'][$change['field']] == 'service' + ) { $orders[$change['order']['id']]['delivery']['service']['code'] = self::newValue($change['newValue']); - } elseif($fields['delivery'][$change['field']]) { + } elseif (isset($fields['delivery'][$change['field']]) + && $fields['delivery'][$change['field']] + ) { $orders[$change['order']['id']]['delivery'][$fields['delivery'][$change['field']]] = self::newValue($change['newValue']); - } elseif($fields['orderAddress'][$change['field']]) { + } elseif (isset($fields['orderAddress'][$change['field']]) + && $fields['orderAddress'][$change['field']] + ) { $orders[$change['order']['id']]['delivery']['address'][$fields['orderAddress'][$change['field']]] = $change['newValue']; - } elseif($fields['integrationDelivery'][$change['field']]) { + } elseif (isset($fields['integrationDelivery'][$change['field']]) + && $fields['integrationDelivery'][$change['field']] + ) { $orders[$change['order']['id']]['delivery']['service'][$fields['integrationDelivery'][$change['field']]] = self::newValue($change['newValue']); - } elseif($fields['customerContragent'][$change['field']]) { + } elseif (isset($fields['customerContragent'][$change['field']]) + && $fields['customerContragent'][$change['field']] + ) { $orders[$change['order']['id']][$fields['customerContragent'][$change['field']]] = self::newValue($change['newValue']); - } elseif(strripos($change['field'], 'custom_') !== false) { + } elseif (strripos($change['field'], 'custom_') !== false) { $orders[$change['order']['id']]['customFields'][str_replace('custom_', '', $change['field'])] = self::newValue($change['newValue']); - } elseif($fields['order'][$change['field']]) { + } elseif (isset($fields['order'][$change['field']]) + && $fields['order'][$change['field']] + ) { $orders[$change['order']['id']][$fields['order'][$change['field']]] = self::newValue($change['newValue']); - } elseif($fields['payment'][$change['field']]) { + } elseif (isset($fields['payment'][$change['field']]) + && $fields['payment'][$change['field']] + ) { $orders[$change['order']['id']]['payments'][$change['payment']['id']][$fields['payment'][$change['field']]] = self::newValue($change['newValue']); } - if(isset($change['created'])) { + if (isset($change['created'])) { $orders[$change['order']['id']]['create'] = 1; } @@ -99,6 +113,38 @@ class RetailcrmHistoryHelper { return $orders; } + public static function assemblyCustomer($customerHistory) + { + if (file_exists(_PS_ROOT_DIR_ . '/modules/retailcrm/objects.xml')) { + $objects = simplexml_load_file(_PS_ROOT_DIR_ . '/modules/retailcrm/objects.xml'); + + foreach($objects->fields->field as $object) { + if ($object["group"] == 'customer') { + $fields[(string)$object["group"]][(string)$object["id"]] = (string)$object; + } + } + } + + $customers = array(); + foreach ($customerHistory as $change) { + $change['customer'] = self::removeEmpty($change['customer']); + + if (isset($customers[$change['customer']['id']])) { + $customers[$change['customer']['id']] = array_merge($customers[$change['customer']['id']], $change['customer']); + } else { + $customers[$change['customer']['id']] = $change['customer']; + } + + if (isset($fields['customer'][$change['field']]) + && $fields['customer'][$change['field']] + ) { + $customers[$change['customer']['id']][$fields['customer'][$change['field']]] = self::newValue($change['newValue']); + } + } + + return $customers; + } + public static function newValue($value) { if(isset($value['code'])) { diff --git a/retailcrm/retailcrm.php b/retailcrm/retailcrm.php index 5be7a29..96c97b0 100644 --- a/retailcrm/retailcrm.php +++ b/retailcrm/retailcrm.php @@ -3,7 +3,7 @@ * @author Retail Driver LCC * @copyright RetailCRM * @license GPL - * @version 2.1.2 + * @version 2.2.0 * @link https://retailcrm.ru * */ @@ -20,12 +20,11 @@ require_once(dirname(__FILE__) . '/bootstrap.php'); class RetailCRM extends Module { - public function __construct() { $this->name = 'retailcrm'; $this->tab = 'export'; - $this->version = '2.1.3'; + $this->version = '2.2.0'; $this->author = 'Retail Driver LCC'; $this->displayName = $this->l('RetailCRM'); $this->description = $this->l('Integration module for RetailCRM'); @@ -75,7 +74,9 @@ class RetailCRM extends Module Configuration::deleteByName('RETAILCRM_API_STATUS') && Configuration::deleteByName('RETAILCRM_API_DELIVERY') && Configuration::deleteByName('RETAILCRM_LAST_SYNC') && - Configuration::deleteByName('RETAILCRM_API_VERSION'); + Configuration::deleteByName('RETAILCRM_API_VERSION') && + Configuration::deleteByName('RETAILCRM_LAST_CUSTOMERS_SYNC') && + Configuration::deleteByName('RETAILCRM_LAST_ORDERS_SYNC'); } public function getContent() @@ -516,8 +517,12 @@ class RetailCRM extends Module foreach ($arAttr as $valAttr) { $arItem = explode(":", $valAttr); - $arProp[$count]['name'] = trim($arItem[0]); - $arProp[$count]['value'] = trim($arItem[1]); + + if ($arItem[0] && $arItem[1]) { + $arProp[$count]['name'] = trim($arItem[0]); + $arProp[$count]['value'] = trim($arItem[1]); + } + $count++; } }