From 24717dd0f1228bdcc383bb4b6834ce058ad363e2 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Fri, 23 Oct 2015 17:41:05 +0300 Subject: [PATCH] new independent structure, override ability --- retailcrm/config.xml | 2 +- retailcrm/config_ru.xml | 6 +- retailcrm/export.tpl | 31 - retailcrm/job/icml.php | 21 + retailcrm/job/sync.php | 5 + retailcrm/job_icml.php | 9 - retailcrm/job_sync.php | 9 - retailcrm/lib/classes/Catalog.php | 98 ++ retailcrm/lib/classes/OrderHistory.php | 459 ++++++++++ retailcrm/{ => lib}/classes/References.php | 0 retailcrm/lib/custom/.gitkeep | 0 retailcrm/{classes => lib/vendor}/Icml.php | 0 .../{classes => lib/vendor}/Retailcrm.php | 0 retailcrm/{classes => lib/vendor}/Service.php | 0 retailcrm/retailcrm.php | 838 ++++-------------- 15 files changed, 743 insertions(+), 735 deletions(-) delete mode 100644 retailcrm/export.tpl create mode 100644 retailcrm/job/icml.php create mode 100644 retailcrm/job/sync.php delete mode 100644 retailcrm/job_icml.php delete mode 100644 retailcrm/job_sync.php create mode 100644 retailcrm/lib/classes/Catalog.php create mode 100644 retailcrm/lib/classes/OrderHistory.php rename retailcrm/{ => lib}/classes/References.php (100%) create mode 100644 retailcrm/lib/custom/.gitkeep rename retailcrm/{classes => lib/vendor}/Icml.php (100%) rename retailcrm/{classes => lib/vendor}/Retailcrm.php (100%) rename retailcrm/{classes => lib/vendor}/Service.php (100%) diff --git a/retailcrm/config.xml b/retailcrm/config.xml index c3bb2c9..40f96b7 100644 --- a/retailcrm/config.xml +++ b/retailcrm/config.xml @@ -2,7 +2,7 @@ retailcrm - + diff --git a/retailcrm/config_ru.xml b/retailcrm/config_ru.xml index 754c073..46eb1b8 100644 --- a/retailcrm/config_ru.xml +++ b/retailcrm/config_ru.xml @@ -2,12 +2,12 @@ retailcrm - - + + 1 1 - + \ No newline at end of file diff --git a/retailcrm/export.tpl b/retailcrm/export.tpl deleted file mode 100644 index ead0361..0000000 --- a/retailcrm/export.tpl +++ /dev/null @@ -1,31 +0,0 @@ - - - - {$shop_name|escape} - {$company|escape} - {$shop_url|escape} - - {foreach from=$categories item=cat name=categories} - {if $cat.id_category > 2} - {$cat.name} - {/if} - {/foreach} - - - {foreach from=$products item=offer name=products} - - {if $offer.available_for_order}Y{else}N{/if} - {$offer.url|escape} - {$offer.price} - {$offer.purchase_price} - {$offer.id_category_default} - {$offer.picture|escape} - {$offer.name|escape} - {if $offer.article} - {$offer.article|escape} - {/if} - - {/foreach} - - - diff --git a/retailcrm/job/icml.php b/retailcrm/job/icml.php new file mode 100644 index 0000000..a5702d0 --- /dev/null +++ b/retailcrm/job/icml.php @@ -0,0 +1,21 @@ +exportCatalog(); + +$icml = new Icml( + Configuration::get('PS_SHOP_NAME'), + _PS_ROOT_DIR_ . '/retailcrm.xml' +); + +$icml->generate($data[0], $data[1]); diff --git a/retailcrm/job/sync.php b/retailcrm/job/sync.php new file mode 100644 index 0000000..5b73e6e --- /dev/null +++ b/retailcrm/job/sync.php @@ -0,0 +1,5 @@ +exportCatalog(); diff --git a/retailcrm/job_sync.php b/retailcrm/job_sync.php deleted file mode 100644 index 11e32a4..0000000 --- a/retailcrm/job_sync.php +++ /dev/null @@ -1,9 +0,0 @@ -orderHistory(); diff --git a/retailcrm/lib/classes/Catalog.php b/retailcrm/lib/classes/Catalog.php new file mode 100644 index 0000000..11c6aaa --- /dev/null +++ b/retailcrm/lib/classes/Catalog.php @@ -0,0 +1,98 @@ +default_lang = (int) Configuration::get('PS_LANG_DEFAULT'); + $this->default_currency = (int) Configuration::get('PS_CURRENCY_DEFAULT'); + $this->default_country = (int) Configuration::get('PS_COUNTRY_DEFAULT'); + } + + public function exportCatalog() + { + + $id_lang = (int) Configuration::get('PS_LANG_DEFAULT'); + $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); + $shop_url = (Configuration::get('PS_SSL_ENABLED') ? _PS_BASE_URL_SSL_ : _PS_BASE_URL_); + + $items = array(); + $categories = array(); + + if ($currency->iso_code == 'RUB') { + $currency->iso_code = 'RUR'; + } + + // Get currencies + $currencies = Currency::getCurrencies(); + + // Get categories + $types = Category::getCategories($id_lang, true, false); + foreach ($types AS $category) + { + $categories[] = array( + 'id' => $category['id_category'], + 'parentId' => $category['id_parent'], + 'name' => $category['name'] + ); + } + + // Get products + $products = Product::getProducts($id_lang, 0, 0, 'name', 'asc'); + foreach ($products AS $product) + { + // Check for home category + $category = $product['id_category_default']; + + if ($category == Configuration::get('PS_HOME_CATEGORY')) { + $temp_categories = Product::getProductCategories($product['id_product']); + + foreach ($temp_categories AS $category) { + if ($category != Configuration::get('PS_HOME_CATEGORY')) + break; + } + + if ($category == Configuration::get('PS_HOME_CATEGORY')) { + continue; + } + + } + + $link = new Link(); + $cover = Image::getCover($product['id_product']); + + $picture = 'http://' . $link->getImageLink($product['link_rewrite'], $product['id_product'].'-'.$cover['id_image'], 'large_default'); + if (!(substr($picture, 0, strlen($shop_url)) === $shop_url)) { + $picture = rtrim($shop_url,"/") . $picture; + } + + $crewrite = Category::getLinkRewrite($product['id_category_default'], $id_lang); + $url = $link->getProductLink($product['id_product'], $product['link_rewrite'], $crewrite); + $version = substr(_PS_VERSION_, 0, 3); + + if ($version == "1.3") + $available_for_order = $product['active'] && $product['quantity']; + else { + $prod = new Product($product['id_product']); + $available_for_order = $product['active'] && $product['available_for_order'] && $prod->checkQty(1); + } + + $items[] = array( + 'id' => $product['id_product'], + 'productId' => $product['id_product'], + 'productActivity' => ($available_for_order) ? 'Y' : 'N', + 'initialPrice' => round($product['price'],2), + 'purchasePrice' => round($product['wholesale_price'], 2), + 'name' => htmlspecialchars(strip_tags($product['name'])), + 'productName' => htmlspecialchars(strip_tags($product['name'])), + 'categoryId' => array($category), + 'picture' => $picture, + 'url' => $url, + 'article' => htmlspecialchars($product['reference']) + ); + } + + return array($categories, $items); + + } +} diff --git a/retailcrm/lib/classes/OrderHistory.php b/retailcrm/lib/classes/OrderHistory.php new file mode 100644 index 0000000..50da3e7 --- /dev/null +++ b/retailcrm/lib/classes/OrderHistory.php @@ -0,0 +1,459 @@ +response = $this->api->ordersHistory( + $startDate = $startFrom, $endDate = $endTime, + $limit = 250, $offset = $counter + ); + $data = array_merge($data, $this->response); + $counter += 250; + } + catch (CurlException $e) { + error_log('orderHistory: connection error', 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + catch (InvalidJsonException $e) { + error_log('orderHistory: ' . $e->getMessage(), 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + } while (!empty($response)); + + /* + * store recieved data into shop database + */ + if (!empty($data)) { + $toUpdate = array(); + + /* + * Customer object. Will be used for further updates. + */ + $this->customer = new Customer(); + + $statuses = array_flip((array)json_decode(Configuration::get('RETAILCRM_API_STATUS'))); + $deliveries = array_flip((array)json_decode(Configuration::get('RETAILCRM_API_DELIVERY'))); + $payments = array_flip((array)json_decode(Configuration::get('RETAILCRM_API_PAYMENT'))); + + foreach ($data as $order) { + if (!array_key_exists('externalId', $order)) { + /* + * create customer if not exist + */ + $this->customer->getByEmail($order['customer']['email']); + + if (!array_key_exists('externalId', $order['customer'])) { + if (Validate::isEmail($order['customer']['email'])) { + + if (!$this->customer->id) + { + $this->customer->firstname = $order['customer']['firstName']; + $this->customer->lastname = $order['customer']['lastName']; + $this->customer->email = $order['customer']['email']; + $this->customer->passwd = substr(str_shuffle(strtolower(sha1(rand() . time()))),0, 5); + + if($this->customer->add()) { + + /* + * create customer address for delivery data + */ + + $this->customer->getByEmail($order['customer']['email']); + $this->customer_id = $this->customer->id; + + $address = new Address(); + $address->id_customer = $this->customer->id; + $address->id_country = $this->default_country; + $address->lastname = $this->customer->lastname; + $address->firstname = $this->customer->firstname; + $address->alias = 'default'; + $address->postcode = $order['deliveryAddress']['index']; + $address->city = $order['deliveryAddress']['city']; + $address->address1 = $order['deliveryAddress']['text']; + $address->phone = $order['phone']; + $address->phone_mobile = $order['phone']; + + $address->add(); + + /* + * store address record id for handle order data + */ + $addr = $this->customer->getAddresses($this->default_lang); + $this->address_id = $addr[0]['id_address']; + } + } else { + $addresses = $this->customer->getAddresses($this->default_lang); + $this->address_id = $addresses[0]['id_address']; + $this->customer_id = $this->customer->id; + } + + /* + * collect customer ids for single fix request + */ + array_push( + $this->customerFix, + array( + 'id' => $order['customer']['id'], + 'externalId' => $this->customer_id + ) + ); + } + } else { + $addresses = $this->customer->getAddresses($this->default_lang); + $this->address_id = $addresses[0]['id_address']; + $this->customer_id = $order['customer']['externalId']; + } + + $delivery = $order['deliveryType']; + $payment = $order['paymentType']; + $state = $order['status']; + + $cart = new Cart(); + $cart->id_currency = $this->default_currency; + $cart->id_lang = $this->default_lang; + $cart->id_customer = $this->customer_id; + $cart->id_address_delivery = (int) $this->address_id; + $cart->id_address_invoice = (int) $this->address_id; + $cart->id_carrier = (int) $deliveries[$delivery]; + + $cart->add(); + + $products = array(); + if(!empty($order['items'])) { + foreach ($order['items'] as $item) { + $product = array(); + $product['id_product'] = (int) $item['offer']['externalId']; + $product['quantity'] = $item['quantity']; + $product['id_address_delivery'] = (int) $this->address_id; + $products[] = $product; + } + } + + $cart->setWsCartRows($products); + $cart->update(); + + /* + * Create order + */ + + $newOrder = new Order(); + $newOrder->id_address_delivery = (int) $this->address_id; + $newOrder->id_address_invoice = (int) $this->address_id; + $newOrder->id_cart = (int) $cart->id; + $newOrder->id_currency = $this->default_currency; + $newOrder->id_lang = $this->default_lang; + $newOrder->id_customer = (int) $this->customer_id; + $newOrder->id_carrier = (int) $deliveries[$delivery]; + $newOrder->payment = $payments[$payment]; + $newOrder->module = (Module::getInstanceByName('advancedcheckout') === false) + ? $payments[$payment] + : 'advancedcheckout' + ; + $newOrder->total_paid = $order['summ'] + $order['deliveryCost']; + $newOrder->total_paid_tax_incl = $order['summ'] + $order['deliveryCost']; + $newOrder->total_paid_tax_excl = $order['summ'] + $order['deliveryCost']; + $newOrder->total_paid_real = $order['summ'] + $order['deliveryCost']; + $newOrder->total_products = $order['summ']; + $newOrder->total_products_wt = $order['summ']; + $newOrder->total_shipping = $order['deliveryCost']; + $newOrder->total_shipping_tax_incl = $order['deliveryCost']; + $newOrder->total_shipping_tax_excl = $order['deliveryCost']; + $newOrder->conversion_rate = 1.000000; + $newOrder->current_state = (int) $statuses[$state]; + $newOrder->delivery_date = $order['deliveryDate']; + $newOrder->date_add = $order['createdAt']; + $newOrder->date_upd = $order['createdAt']; + $newOrder->valid = 1; + $newOrder->secure_key = md5(time()); + + if (isset($order['discount'])) + { + $newOrder->total_discounts = $order['discount']; + } + + $newOrder->add(false, false); + + /* + * collect order ids for single fix request + */ + array_push( + $this->orderFix, + array( + 'id' => $order['id'], + 'externalId' => $newOrder->id + ) + ); + + /* + * Create order details + */ + $product_list = array(); + foreach ($order['items'] as $item) { + $product = new Product((int) $item['offer']['externalId'], false, $this->default_lang); + $qty = $item['quantity']; + $product_list[] = array('product' =>$product, 'quantity' => $qty); + } + + $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 ($product_list as $product) { + $query .= '(' + .(int) $newOrder->id.', + 0, + '. $this->context->shop->id.', + '.(int) $product['product']->id.', + 0, + '.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.', + '.$product['product']->price.', + '.$product['product']->price.', + '.$product['product']->price.' + ),'; + } + + Db::getInstance()->execute(rtrim($query, ',')); + + try { + $this->api->customersFixExternalIds($this->customerFix); + $this->api->ordesrFixExternalIds($this->orderFix); + } + catch (CurlException $e) { + error_log('fixExternalId: connection error', 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + continue; + } + catch (InvalidJsonException $e) { + error_log('fixExternalId: ' . $e->getMessage(), 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + continue; + } + + } else { + if (!in_array($order['id'], $toUpdate)) + { + /* + * take last order update only + */ + $toUpdate[] = $order['id']; + if ($order['paymentType'] != null && $order['deliveryType'] != null && $order['status'] != null) { + $orderToUpdate = new Order((int) $order['externalId']); + + /* + * check status + */ + $stype = $order['status']; + if ($statuses[$stype] != null) { + if ($statuses[$stype] != $orderToUpdate->current_state) { + Db::getInstance()->execute(' + UPDATE `'._DB_PREFIX_.'orders` + SET `current_state` = \''.$statuses[$stype].'\' + WHERE `id_order` = '.(int) $order['externalId']); + } + } + + /* + * check delivery type + */ + $dtype = $order['deliveryType']; + if ($deliveries[$dtype] != null) { + if ($deliveries[$dtype] != $orderToUpdate->id_carrier) { + Db::getInstance()->execute(' + UPDATE `'._DB_PREFIX_.'orders` + SET `id_carrier` = \''.$deliveries[$dtype].'\' + WHERE `id_order` = '.(int) $order['externalId']); + Db::getInstance()->execute(' + UPDATE `'._DB_PREFIX_.'order_carrier` + SET `id_carrier` = \''.$deliveries[$dtype].'\' + WHERE `id_order` = \''.$orderToUpdate->id.'\''); + } + } + + /* + * check payment type + */ + $ptype = $order['paymentType']; + if ($payments[$ptype] != null) { + if ($payments[$ptype] != $orderToUpdate->payment) { + Db::getInstance()->execute(' + UPDATE `'._DB_PREFIX_.'orders` + SET `payment` = \''.$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.'\''); + + } + } + + /* + * check items + */ + + /* + * Clean deleted + */ + foreach ($order['items'] as $key => $item) { + if (isset($item['deleted']) && $item['deleted'] == true) { + Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.'order_detail` + WHERE `id_order` = '. $orderToUpdate->id .' + AND `product_id` = '.$item['id']); + + unset($order['items'][$key]); + } + } + + /* + * check quantity + */ + + foreach ($orderToUpdate->getProductsDetail() as $orderItem) { + foreach ($order['items'] as $key => $item) { + if ($item['offer']['externalId'] == $orderItem['product_id']) { + 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']); + } + + unset($order['items'][$key]); + } + } + } + + /* + * check new items + */ + if (!empty($order['items'])) { + foreach ($order['items'] as $key => $newItem) { + $product = new Product((int) $newItem['offer']['externalId'], false, $this->default_lang); + $qty = $newItem['quantity']; + $product_list[] = array('product' =>$product, 'quantity' => $qty); + } + + + $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 ($product_list as $product) { + $query .= '(' + .(int) $orderToUpdate->id.', + 0, + '. $this->context->shop->id.', + '.(int) $product['product']->id.', + 0, + '.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.', + '.$product['product']->price.', + '.$product['product']->price.', + '.$product['product']->price.' + ),'; + } + + Db::getInstance()->execute(rtrim($query, ',')); + unset($order['items'][$key]); + } + + /* + * Fix prices & discounts + * Discounts only for whole order + */ + $orderDiscout = null; + $orderTotal = $order['summ']; + + if (isset($order['discount']) && $order['discount'] > 0) { + if ($order['discount'] != $orderToUpdate->total_discounts) { + $orderDiscout = ($orderDiscout == null) ? $order['discount'] : $order['discount'] + $orderDiscout; + } + } + + if (isset($order['discountPercent']) && $order['discountPercent'] > 0) { + $percent = ($order['summ'] * $order['discountPercent'])/100; + if ($percent != $orderToUpdate->total_discounts) { + $orderDiscout = ($orderDiscout == null) ? $percent : $percent + $orderDiscout; + } + } + + $totalDiscount = ($orderDiscout == null) ? $orderToUpdate->total_discounts : $orderDiscout; + + if ($totalDiscount != $orderToUpdate->total_discounts || $orderTotal != $orderToUpdate->total_paid) { + Db::getInstance()->execute(' + UPDATE `'._DB_PREFIX_.'orders` + SET `total_discounts` = '.$totalDiscount.', + `total_discounts_tax_incl` = '.$totalDiscount.', + `total_discounts_tax_excl` = '.$totalDiscount.', + `total_paid` = '.$orderTotal.', + `total_paid_tax_incl` = '.$orderTotal.', + `total_paid_tax_excl` = '.$orderTotal.' + WHERE `id_order` = '.(int) $order['externalId']); + } + } + } + } + } + + /* + * Update last sync timestamp + */ + try { + Configuration::updateValue( + 'RETAILCRM_LAST_SYNC', + date_format($this->api->getGeneratedAt(), 'Y-m-d H:i:s') + ); + } + catch (CurlException $e) { + error_log('getLastSync: connection error', 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + catch (InvalidJsonException $e) { + error_log('getLastSync: ' . $e->getMessage(), 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + + return count($data) . " records was synced"; + + } else { + return 'Nothing to sync'; + } + + } +} \ No newline at end of file diff --git a/retailcrm/classes/References.php b/retailcrm/lib/classes/References.php similarity index 100% rename from retailcrm/classes/References.php rename to retailcrm/lib/classes/References.php diff --git a/retailcrm/lib/custom/.gitkeep b/retailcrm/lib/custom/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/retailcrm/classes/Icml.php b/retailcrm/lib/vendor/Icml.php similarity index 100% rename from retailcrm/classes/Icml.php rename to retailcrm/lib/vendor/Icml.php diff --git a/retailcrm/classes/Retailcrm.php b/retailcrm/lib/vendor/Retailcrm.php similarity index 100% rename from retailcrm/classes/Retailcrm.php rename to retailcrm/lib/vendor/Retailcrm.php diff --git a/retailcrm/classes/Service.php b/retailcrm/lib/vendor/Service.php similarity index 100% rename from retailcrm/classes/Service.php rename to retailcrm/lib/vendor/Service.php diff --git a/retailcrm/retailcrm.php b/retailcrm/retailcrm.php index cd6ee62..439bc89 100644 --- a/retailcrm/retailcrm.php +++ b/retailcrm/retailcrm.php @@ -1,26 +1,33 @@ name = 'retailcrm'; $this->tab = 'market_place'; - $this->version = '0.2'; + $this->version = '1.1'; $this->author = 'Retail Driver LCC'; $this->displayName = $this->l('RetailCRM'); @@ -119,7 +126,8 @@ class RetailCRM extends Module $output .= $this->displayConfirmation($this->l('Settings updated')); } } - $this->display(__FILE__, 'intarocrm.tpl'); + + $this->display(__FILE__, 'retailcrm.tpl'); return $output.$this->displayForm(); } @@ -282,676 +290,6 @@ class RetailCRM extends Module return $helper->generateForm($fields_form); } - public function hookNewOrder($params) - { - return $this->hookActionOrderStatusPostUpdate($params); - } - - public function hookActionPaymentConfirmation($params) - { - $this->api->ordersEdit( - array( - 'externalId' => $params['id_order'], - 'paymentStatus' => 'paid', - 'createdAt' => $params['cart']->date_upd - ) - ); - - return $this->hookActionOrderStatusPostUpdate($params); - } - - public function hookActionOrderStatusPostUpdate($params) - { - $address_id = Address::getFirstCustomerAddressId($params['cart']->id_customer); - $sql = 'SELECT * FROM '._DB_PREFIX_.'address WHERE id_address='.(int) $address_id; - $address = Db::getInstance()->ExecuteS($sql); - $address = $address[0]; - $delivery = json_decode(Configuration::get('RETAILCRM_API_DELIVERY')); - $payment = json_decode(Configuration::get('RETAILCRM_API_PAYMENT')); - $inCart = $params['cart']->getProducts(); - - if (isset($params['orderStatus'])) { - try { - $this->api->customersCreate( - array( - 'externalId' => $params['cart']->id_customer, - 'lastName' => $params['customer']->lastname, - 'firstName' => $params['customer']->firstname, - 'email' => $params['customer']->email, - 'phones' => array( - array( - 'number' => $address['phone'], - 'type' => 'mobile' - ), - array( - 'number' => $address['phone_mobile'], - 'type' => 'mobile' - ) - ), - 'createdAt' => $params['customer']->date_add - ) - ); - } - catch (CurlException $e) { - error_log("customerCreate: connection error", 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - catch (InvalidJsonException $e) { - error_log('customerCreate: ' . $e->getMessage(), 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - - try { - $items = array(); - foreach ($inCart as $item) { - $items[] = array( - 'initialPrice' => $item['price'], - 'quantity' => $item['quantity'], - 'productId' => $item['id_product'], - 'productName' => $item['name'], - 'createdAt' => $item['date_add'] - ); - } - - $dTypeKey = $params['cart']->id_carrier; - if (Module::getInstanceByName('advancedcheckout') === false) { - $pTypeKey = $params['order']->module; - } else { - $pTypeKey = $params['order']->payment; - } - $this->api->ordersCreate( - array( - 'externalId' => $params['order']->id, - 'orderType' => 'eshop-individual', - 'orderMethod' => 'shopping-cart', - 'customerId' => $params['cart']->id_customer, - 'firstName' => $params['customer']->firstname, - 'lastName' => $params['customer']->lastname, - 'phone' => $address['phone'], - 'email' => $params['customer']->email, - 'paymentStatus' => 'not-paid', - 'paymentType' => $payment->$pTypeKey, - 'deliveryType' => $delivery->$dTypeKey, - 'deliveryCost' => $params['order']->total_shipping, - 'status' => 'new', - 'deliveryAddress' => array( - 'city' => $address['city'], - 'index' => $address['postcode'], - 'text' => $address['address1'], - ), - 'discount' => $params['order']->total_discounts, - 'items' => $items, - 'createdAt' => $params['order']->date_add - ) - ); - } - catch (CurlException $e) { - error_log('orderCreate: connection error', 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - catch (InvalidJsonException $e) { - error_log('orderCreate: ' . $e->getMessage(), 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - - } - - if (isset($params['newOrderStatus']) && !empty($params['newOrderStatus'])) { - $statuses = OrderState::getOrderStates($this->default_lang); - $aStatuses = json_decode(Configuration::get('RETAILCRM_API_STATUS')); - foreach ($statuses as $status) { - if ($status['name'] == $params['newOrderStatus']->name) { - $currStatus = $status['id_order_state']; - try { - $this->api->ordersEdit( - array( - 'externalId' => $params['id_order'], - 'status' => $aStatuses->$currStatus, - 'createdAt' => $params['cart']->date_upd - ) - ); - } - catch (CurlException $e) { - error_log('orderStatusUpdate: connection error', 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - catch (InvalidJsonException $e) { - error_log('orderStatusUpdate: ' . $e->getMessage(), 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - } - } - } - } - - public function exportCatalog() - { - global $smarty; - $shop_url = (Configuration::get('PS_SSL_ENABLED') ? _PS_BASE_URL_SSL_ : _PS_BASE_URL_); - $id_lang = (int) Configuration::get('PS_LANG_DEFAULT'); - $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); - if ($currency->iso_code == 'RUB') { - $currency->iso_code = 'RUR'; - } - - // Get currencies - $currencies = Currency::getCurrencies(); - - // Get categories - $categories = Category::getCategories($id_lang, true, false); - - // Get products - $products = Product::getProducts($id_lang, 0, 0, 'name', 'asc'); - foreach ($products AS $product) - { - // Check for home category - $category = $product['id_category_default']; - if ($category == Configuration::get('PS_HOME_CATEGORY')) { - $temp_categories = Product::getProductCategories($product['id_product']); - - foreach ($temp_categories AS $category) { - if ($category != Configuration::get('PS_HOME_CATEGORY')) - break; - } - - if ($category == Configuration::get('PS_HOME_CATEGORY')) { - continue; - } - - } - $link = new Link(); - $cover = Image::getCover($product['id_product']); - - $picture = 'http://' . $link->getImageLink($product['link_rewrite'], $product['id_product'].'-'.$cover['id_image'], 'large_default'); - if (!(substr($picture, 0, strlen($shop_url)) === $shop_url)) - $picture = rtrim($shop_url,"/") . $picture; - $crewrite = Category::getLinkRewrite($product['id_category_default'], $id_lang); - $url = $link->getProductLink($product['id_product'], $product['link_rewrite'], $crewrite); - $version = substr(_PS_VERSION_, 0, 3); - - if ($version == "1.3") - $available_for_order = $product['active'] && $product['quantity']; - else { - $prod = new Product($product['id_product']); - $available_for_order = $product['active'] && $product['available_for_order'] && $prod->checkQty(1); - } - - $items[] = array('id_product' => $product['id_product'], - 'available_for_order' => $available_for_order, - 'price' => round($product['price'],2), - 'purchase_price' => round($product['wholesale_price'], 2), - 'name' => htmlspecialchars(strip_tags($product['name'])), - 'article' => htmlspecialchars($product['reference']), - 'id_category_default' => $category, - 'picture' => $picture, - 'url' => $url - ); - } - - foreach ($this->custom_attributes as $i => $value) { - $attr = Configuration::get($value); - $smarty->assign(strtolower($value), $attr); - } - - $smarty->assign('currencies', $currencies); - $smarty->assign('currency', $currency->iso_code); - $smarty->assign('categories', $categories); - $smarty->assign('products', $items); - $smarty->assign('shop_name', Configuration::get('PS_SHOP_NAME')); - $smarty->assign('company', Configuration::get('PS_SHOP_NAME')); - $smarty->assign('shop_url', $shop_url . __PS_BASE_URI__); - return $this->display(__FILE__, 'export.tpl'); - } - - public function orderHistory() - { - /* - * get last sync date - */ - $lastSync = Configuration::get('RETAILCRM_LAST_SYNC'); - - $startFrom = ($lastSync === false) ? null : $lastSync; - $endTime = date('Y-m-d H:i:s'); - - $data = array(); - $counter = 0; - - /* - * retrive orders from crm since last update - */ - do { - try { - $this->response = $this->api->ordersHistory( - $startDate = $startFrom, $endDate = $endTime, - $limit = 250, $offset = $counter - ); - $data = array_merge($data, $this->response); - $counter += 250; - } - catch (CurlException $e) { - error_log('orderHistory: connection error', 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - catch (InvalidJsonException $e) { - error_log('orderHistory: ' . $e->getMessage(), 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - } while (!empty($response)); - - /* - * store recieved data into shop database - */ - if (!empty($data)) { - $toUpdate = array(); - - /* - * Customer object. Will be used for further updates. - */ - $this->customer = new Customer(); - - $statuses = array_flip((array)json_decode(Configuration::get('RETAILCRM_API_STATUS'))); - $deliveries = array_flip((array)json_decode(Configuration::get('RETAILCRM_API_DELIVERY'))); - $payments = array_flip((array)json_decode(Configuration::get('RETAILCRM_API_PAYMENT'))); - - foreach ($data as $order) { - if (!array_key_exists('externalId', $order)) { - /* - * create customer if not exist - */ - $this->customer->getByEmail($order['customer']['email']); - - if (!array_key_exists('externalId', $order['customer'])) { - if (Validate::isEmail($order['customer']['email'])) { - - if (!$this->customer->id) - { - $this->customer->firstname = $order['customer']['firstName']; - $this->customer->lastname = $order['customer']['lastName']; - $this->customer->email = $order['customer']['email']; - $this->customer->passwd = substr(str_shuffle(strtolower(sha1(rand() . time()))),0, 5); - - if($this->customer->add()) { - - /* - * create customer address for delivery data - */ - - $this->customer->getByEmail($order['customer']['email']); - $this->customer_id = $this->customer->id; - - $address = new Address(); - $address->id_customer = $this->customer->id; - $address->id_country = $this->default_country; - $address->lastname = $this->customer->lastname; - $address->firstname = $this->customer->firstname; - $address->alias = 'default'; - $address->postcode = $order['deliveryAddress']['index']; - $address->city = $order['deliveryAddress']['city']; - $address->address1 = $order['deliveryAddress']['text']; - $address->phone = $order['phone']; - $address->phone_mobile = $order['phone']; - - $address->add(); - - /* - * store address record id for handle order data - */ - $addr = $this->customer->getAddresses($this->default_lang); - $this->address_id = $addr[0]['id_address']; - } - } else { - $addresses = $this->customer->getAddresses($this->default_lang); - $this->address_id = $addresses[0]['id_address']; - $this->customer_id = $this->customer->id; - } - - /* - * collect customer ids for single fix request - */ - array_push( - $this->customerFix, - array( - 'id' => $order['customer']['id'], - 'externalId' => $this->customer_id - ) - ); - } - } else { - $addresses = $this->customer->getAddresses($this->default_lang); - $this->address_id = $addresses[0]['id_address']; - $this->customer_id = $order['customer']['externalId']; - } - - $delivery = $order['deliveryType']; - $payment = $order['paymentType']; - $state = $order['status']; - - $cart = new Cart(); - $cart->id_currency = $this->default_currency; - $cart->id_lang = $this->default_lang; - $cart->id_customer = $this->customer_id; - $cart->id_address_delivery = (int) $this->address_id; - $cart->id_address_invoice = (int) $this->address_id; - $cart->id_carrier = (int) $deliveries[$delivery]; - - $cart->add(); - - $products = array(); - if(!empty($order['items'])) { - foreach ($order['items'] as $item) { - $product = array(); - $product['id_product'] = (int) $item['offer']['externalId']; - $product['quantity'] = $item['quantity']; - $product['id_address_delivery'] = (int) $this->address_id; - $products[] = $product; - } - } - - $cart->setWsCartRows($products); - $cart->update(); - - /* - * Create order - */ - - $newOrder = new Order(); - $newOrder->id_address_delivery = (int) $this->address_id; - $newOrder->id_address_invoice = (int) $this->address_id; - $newOrder->id_cart = (int) $cart->id; - $newOrder->id_currency = $this->default_currency; - $newOrder->id_lang = $this->default_lang; - $newOrder->id_customer = (int) $this->customer_id; - $newOrder->id_carrier = (int) $deliveries[$delivery]; - $newOrder->payment = $payments[$payment]; - $newOrder->module = (Module::getInstanceByName('advancedcheckout') === false) - ? $payments[$payment] - : 'advancedcheckout' - ; - $newOrder->total_paid = $order['summ'] + $order['deliveryCost']; - $newOrder->total_paid_tax_incl = $order['summ'] + $order['deliveryCost']; - $newOrder->total_paid_tax_excl = $order['summ'] + $order['deliveryCost']; - $newOrder->total_paid_real = $order['summ'] + $order['deliveryCost']; - $newOrder->total_products = $order['summ']; - $newOrder->total_products_wt = $order['summ']; - $newOrder->total_shipping = $order['deliveryCost']; - $newOrder->total_shipping_tax_incl = $order['deliveryCost']; - $newOrder->total_shipping_tax_excl = $order['deliveryCost']; - $newOrder->conversion_rate = 1.000000; - $newOrder->current_state = (int) $statuses[$state]; - $newOrder->delivery_date = $order['deliveryDate']; - $newOrder->date_add = $order['createdAt']; - $newOrder->date_upd = $order['createdAt']; - $newOrder->valid = 1; - $newOrder->secure_key = md5(time()); - - if (isset($order['discount'])) - { - $newOrder->total_discounts = $order['discount']; - } - - $newOrder->add(false, false); - - /* - * collect order ids for single fix request - */ - array_push( - $this->orderFix, - array( - 'id' => $order['id'], - 'externalId' => $newOrder->id - ) - ); - - /* - * Create order details - */ - $product_list = array(); - foreach ($order['items'] as $item) { - $product = new Product((int) $item['offer']['externalId'], false, $this->default_lang); - $qty = $item['quantity']; - $product_list[] = array('product' =>$product, 'quantity' => $qty); - } - - $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 ($product_list as $product) { - $query .= '(' - .(int) $newOrder->id.', - 0, - '. $this->context->shop->id.', - '.(int) $product['product']->id.', - 0, - '.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.', - '.$product['product']->price.', - '.$product['product']->price.', - '.$product['product']->price.' - ),'; - } - - Db::getInstance()->execute(rtrim($query, ',')); - - try { - $this->api->customersFixExternalIds($this->customerFix); - $this->api->ordesrFixExternalIds($this->orderFix); - } - catch (CurlException $e) { - error_log('fixExternalId: connection error', 3, _PS_ROOT_DIR . "log/retailcrm.log"); - continue; - } - catch (InvalidJsonException $e) { - error_log('fixExternalId: ' . $e->getMessage(), 3, _PS_ROOT_DIR . "log/retailcrm.log"); - continue; - } - - } else { - if (!in_array($order['id'], $toUpdate)) - { - /* - * take last order update only - */ - $toUpdate[] = $order['id']; - if ($order['paymentType'] != null && $order['deliveryType'] != null && $order['status'] != null) { - $orderToUpdate = new Order((int) $order['externalId']); - - /* - * check status - */ - $stype = $order['status']; - if ($statuses[$stype] != null) { - if ($statuses[$stype] != $orderToUpdate->current_state) { - Db::getInstance()->execute(' - UPDATE `'._DB_PREFIX_.'orders` - SET `current_state` = \''.$statuses[$stype].'\' - WHERE `id_order` = '.(int) $order['externalId']); - } - } - - /* - * check delivery type - */ - $dtype = $order['deliveryType']; - if ($deliveries[$dtype] != null) { - if ($deliveries[$dtype] != $orderToUpdate->id_carrier) { - Db::getInstance()->execute(' - UPDATE `'._DB_PREFIX_.'orders` - SET `id_carrier` = \''.$deliveries[$dtype].'\' - WHERE `id_order` = '.(int) $order['externalId']); - Db::getInstance()->execute(' - UPDATE `'._DB_PREFIX_.'order_carrier` - SET `id_carrier` = \''.$deliveries[$dtype].'\' - WHERE `id_order` = \''.$orderToUpdate->id.'\''); - } - } - - /* - * check payment type - */ - $ptype = $order['paymentType']; - if ($payments[$ptype] != null) { - if ($payments[$ptype] != $orderToUpdate->payment) { - Db::getInstance()->execute(' - UPDATE `'._DB_PREFIX_.'orders` - SET `payment` = \''.$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.'\''); - - } - } - - /* - * check items - */ - - /* - * Clean deleted - */ - foreach ($order['items'] as $key => $item) { - if (isset($item['deleted']) && $item['deleted'] == true) { - Db::getInstance()->execute(' - DELETE FROM `'._DB_PREFIX_.'order_detail` - WHERE `id_order` = '. $orderToUpdate->id .' - AND `product_id` = '.$item['id']); - - unset($order['items'][$key]); - } - } - - /* - * check quantity - */ - - foreach ($orderToUpdate->getProductsDetail() as $orderItem) { - foreach ($order['items'] as $key => $item) { - if ($item['offer']['externalId'] == $orderItem['product_id']) { - 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']); - } - - unset($order['items'][$key]); - } - } - } - - /* - * check new items - */ - if (!empty($order['items'])) { - foreach ($order['items'] as $key => $newItem) { - $product = new Product((int) $newItem['offer']['externalId'], false, $this->default_lang); - $qty = $newItem['quantity']; - $product_list[] = array('product' =>$product, 'quantity' => $qty); - } - - - $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 ($product_list as $product) { - $query .= '(' - .(int) $orderToUpdate->id.', - 0, - '. $this->context->shop->id.', - '.(int) $product['product']->id.', - 0, - '.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.', - '.$product['product']->price.', - '.$product['product']->price.', - '.$product['product']->price.' - ),'; - } - - Db::getInstance()->execute(rtrim($query, ',')); - unset($order['items'][$key]); - } - - /* - * Fix prices & discounts - * Discounts only for whole order - */ - $orderDiscout = null; - $orderTotal = $order['summ']; - - if (isset($order['discount']) && $order['discount'] > 0) { - if ($order['discount'] != $orderToUpdate->total_discounts) { - $orderDiscout = ($orderDiscout == null) ? $order['discount'] : $order['discount'] + $orderDiscout; - } - } - - if (isset($order['discountPercent']) && $order['discountPercent'] > 0) { - $percent = ($order['summ'] * $order['discountPercent'])/100; - if ($percent != $orderToUpdate->total_discounts) { - $orderDiscout = ($orderDiscout == null) ? $percent : $percent + $orderDiscout; - } - } - - $totalDiscount = ($orderDiscout == null) ? $orderToUpdate->total_discounts : $orderDiscout; - - if ($totalDiscount != $orderToUpdate->total_discounts || $orderTotal != $orderToUpdate->total_paid) { - Db::getInstance()->execute(' - UPDATE `'._DB_PREFIX_.'orders` - SET `total_discounts` = '.$totalDiscount.', - `total_discounts_tax_incl` = '.$totalDiscount.', - `total_discounts_tax_excl` = '.$totalDiscount.', - `total_paid` = '.$orderTotal.', - `total_paid_tax_incl` = '.$orderTotal.', - `total_paid_tax_excl` = '.$orderTotal.' - WHERE `id_order` = '.(int) $order['externalId']); - } - } - } - } - } - - /* - * Update last sync timestamp - */ - try { - Configuration::updateValue( - 'RETAILCRM_LAST_SYNC', - date_format($this->api->getGeneratedAt(), 'Y-m-d H:i:s') - ); - } - catch (CurlException $e) { - error_log('getLastSync: connection error', 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - catch (InvalidJsonException $e) { - error_log('getLastSync: ' . $e->getMessage(), 3, _PS_ROOT_DIR . "log/retailcrm.log"); - } - - return count($data) . " records was synced"; - - } else { - return 'Nothing to sync'; - } - - } - public function getAddressFields() { $addressFields = array(); @@ -1048,4 +386,140 @@ class RetailCRM extends Module return $addressFields; } + + public function hookNewOrder($params) + { + return $this->hookActionOrderStatusPostUpdate($params); + } + + public function hookActionPaymentConfirmation($params) + { + $this->api->ordersEdit( + array( + 'externalId' => $params['id_order'], + 'paymentStatus' => 'paid', + 'createdAt' => $params['cart']->date_upd + ) + ); + + return $this->hookActionOrderStatusPostUpdate($params); + } + + public function hookActionOrderStatusPostUpdate($params) + { + $address_id = Address::getFirstCustomerAddressId($params['cart']->id_customer); + $sql = 'SELECT * FROM '._DB_PREFIX_.'address WHERE id_address='.(int) $address_id; + $address = Db::getInstance()->ExecuteS($sql); + $address = $address[0]; + $delivery = json_decode(Configuration::get('RETAILCRM_API_DELIVERY')); + $payment = json_decode(Configuration::get('RETAILCRM_API_PAYMENT')); + $inCart = $params['cart']->getProducts(); + + if (isset($params['orderStatus'])) { + try { + $this->api->customersCreate( + array( + 'externalId' => $params['cart']->id_customer, + 'lastName' => $params['customer']->lastname, + 'firstName' => $params['customer']->firstname, + 'email' => $params['customer']->email, + 'phones' => array( + array( + 'number' => $address['phone'], + 'type' => 'mobile' + ), + array( + 'number' => $address['phone_mobile'], + 'type' => 'mobile' + ) + ), + 'createdAt' => $params['customer']->date_add + ) + ); + } + catch (CurlException $e) { + error_log("customerCreate: connection error", 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + catch (InvalidJsonException $e) { + error_log('customerCreate: ' . $e->getMessage(), 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + + try { + $items = array(); + foreach ($inCart as $item) { + $items[] = array( + 'initialPrice' => $item['price'], + 'quantity' => $item['quantity'], + 'productId' => $item['id_product'], + 'productName' => $item['name'], + 'createdAt' => $item['date_add'] + ); + } + + $dTypeKey = $params['cart']->id_carrier; + if (Module::getInstanceByName('advancedcheckout') === false) { + $pTypeKey = $params['order']->module; + } else { + $pTypeKey = $params['order']->payment; + } + $this->api->ordersCreate( + array( + 'externalId' => $params['order']->id, + 'orderType' => 'eshop-individual', + 'orderMethod' => 'shopping-cart', + 'customerId' => $params['cart']->id_customer, + 'firstName' => $params['customer']->firstname, + 'lastName' => $params['customer']->lastname, + 'phone' => $address['phone'], + 'email' => $params['customer']->email, + 'paymentStatus' => 'not-paid', + 'paymentType' => $payment->$pTypeKey, + 'deliveryType' => $delivery->$dTypeKey, + 'deliveryCost' => $params['order']->total_shipping, + 'status' => 'new', + 'deliveryAddress' => array( + 'city' => $address['city'], + 'index' => $address['postcode'], + 'text' => $address['address1'], + ), + 'discount' => $params['order']->total_discounts, + 'items' => $items, + 'createdAt' => $params['order']->date_add + ) + ); + } + catch (CurlException $e) { + error_log('orderCreate: connection error', 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + catch (InvalidJsonException $e) { + error_log('orderCreate: ' . $e->getMessage(), 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + + } + + if (isset($params['newOrderStatus']) && !empty($params['newOrderStatus'])) { + $statuses = OrderState::getOrderStates($this->default_lang); + $aStatuses = json_decode(Configuration::get('RETAILCRM_API_STATUS')); + foreach ($statuses as $status) { + if ($status['name'] == $params['newOrderStatus']->name) { + $currStatus = $status['id_order_state']; + try { + $this->api->ordersEdit( + array( + 'externalId' => $params['id_order'], + 'status' => $aStatuses->$currStatus, + 'createdAt' => $params['cart']->date_upd + ) + ); + } + catch (CurlException $e) { + error_log('orderStatusUpdate: connection error', 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + catch (InvalidJsonException $e) { + error_log('orderStatusUpdate: ' . $e->getMessage(), 3, _PS_ROOT_DIR_ . "log/retailcrm.log"); + } + } + } + } + } }