From f55240d759067e3ad59c1ea3c8dab57bf085c0dd Mon Sep 17 00:00:00 2001 From: dkorol Date: Mon, 25 Jul 2016 17:21:15 +0300 Subject: [PATCH] history, fixes --- admin/model/retailcrm/history.php | 42 ++- admin/model/retailcrm/icml.php | 296 ++++++++++++------ catalog/controller/module/retailcrm.php | 13 + catalog/model/retailcrm/order.php | 76 ++++- system/cron/dispatch.php | 2 +- .../library/retailcrm/OpencartApiClient.php | 3 +- 6 files changed, 318 insertions(+), 114 deletions(-) diff --git a/admin/model/retailcrm/history.php b/admin/model/retailcrm/history.php index 3e203c6..0907b06 100644 --- a/admin/model/retailcrm/history.php +++ b/admin/model/retailcrm/history.php @@ -19,6 +19,7 @@ class ModelRetailcrmHistory extends Model } $this->load->model('retailcrm/references'); $this->load->model('catalog/product'); + $this->load->model('catalog/option'); $this->load->model('localisation/zone'); $this->load->language('module/retailcrm'); @@ -189,19 +190,36 @@ class ModelRetailcrmHistory extends Model $data['order_product'] = array(); foreach ($order['items'] as $item) { - $product = $this->model_catalog_product->getProduct($item['offer']['externalId']); - $data['order_product'][] = array( - 'product_id' => $item['offer']['externalId'], - 'name' => $item['offer']['name'], - 'quantity' => $item['quantity'], - 'price' => $item['initialPrice'], - 'total' => $item['initialPrice'] * $item['quantity'], - 'model' => $product['model'], + //$product = $this->model_catalog_product->getProduct($item['offer']['externalId']); + $productId = $item['offer']['externalId']; + $options = array(); + if(mb_strpos($item['offer']['externalId'], '#') > 1) { + $offer = explode('#', $item['offer']['externalId']); + $productId = $offer[0]; + $optionsFromCRM = explode('_', $offer[1]); - // this data will not retrive from crm - 'order_product_id' => '', - 'tax' => 0, - 'reward' => 0 + foreach($optionsFromCRM as $optionFromCRM) { + $optionData = explode('-', $optionFromCRM); + $productOptionId = $optionData[0]; + $optionValueId = $optionData[1]; + + $productOptions = $this->model_catalog_product->getProductOptions($productId); + + foreach($productOptions as $productOption) { + if($productOptionId == $productOption['product_option_id']) { + foreach($productOption['product_option_value'] as $productOptionValue) { + if($productOptionValue['option_value_id'] == $optionValueId) { + $options[$productOptionId] = $productOptionValue['product_option_value_id']; + } + } + } + } + } + } + $data['order_product'][] = array( + 'product_id' => $productId, + 'quantity' => $item['quantity'], + 'option' => $options ); } diff --git a/admin/model/retailcrm/icml.php b/admin/model/retailcrm/icml.php index 39ac931..2d6b5c5 100644 --- a/admin/model/retailcrm/icml.php +++ b/admin/model/retailcrm/icml.php @@ -10,11 +10,15 @@ class ModelRetailcrmIcml extends Model protected $eCategories; protected $eOffers; + private $options; + private $optionValues; + public function generateICML() { $this->load->language('module/retailcrm'); $this->load->model('catalog/category'); $this->load->model('catalog/product'); + $this->load->model('catalog/option'); $this->load->model('catalog/manufacturer'); $string = ' @@ -95,107 +99,192 @@ class ModelRetailcrmIcml extends Model $products = $this->model_catalog_product->getProducts(array()); - foreach ($products as $offer) { - - $e = $this->eOffers->appendChild($this->dd->createElement('offer')); - $e->setAttribute('id', $offer['product_id']); - $e->setAttribute('productId', $offer['product_id']); - $e->setAttribute('quantity', $offer['quantity']); - - /** - * Offer activity - */ - $activity = $offer['status'] == 1 ? 'Y' : 'N'; - $e->appendChild( - $this->dd->createElement('productActivity') - )->appendChild( - $this->dd->createTextNode($activity) - ); - - /** - * Offer categories - */ - $categories = $this->model_catalog_product - ->getProductCategories($offer['product_id']); - - if (!empty($categories)) { - foreach ($categories as $category) { - $e->appendChild($this->dd->createElement('categoryId')) - ->appendChild( - $this->dd->createTextNode($category) - ); + foreach ($products as $product) { + // Формируем офферы отнсительно доступных опций + $options = $this->model_catalog_product->getProductOptions($product['product_id']); + $offerOptions = array('select', 'radio'); + $requiredOptions = array(); + $notRequiredOptions = array(); + // Оставляем опции связанные с вариациями товаров, сортируем по параметру обязательный или нет + foreach($options as $option) { + if(in_array($option['type'], $offerOptions)) { + if($option['required']) { + $requiredOptions[] = $option; + } else { + $notRequiredOptions[] = $option; + } } } + $offers = array(); + // Сначала совмещаем все обязательные опции + foreach($requiredOptions as $requiredOption) { + // Если первая итерация + if(empty($offers)) { + foreach($requiredOption['product_option_value'] as $optionValue) { + $offers[$requiredOption['product_option_id'].':'.$requiredOption['option_id'].'-'.$optionValue['option_value_id']] = (float)$optionValue['price']; + } + } else { + foreach($offers as $optionKey => $optionCost) { + unset($offers[$optionKey]); // Работая в контексте обязательных опций не забываем удалять прошлые обязательные опции, т.к. они должны быть скомбинированы с другими обязательными опциями + foreach($requiredOption['product_option_value'] as $optionValue) { + $offers[$optionKey.'_'.$requiredOption['product_option_id'].':'.$requiredOption['option_id'].'-'.$optionValue['option_value_id']] = $optionCost + (float)$optionValue['price']; + } + } + } + } + // Совмещаем или добавляем необязательные опции, учитывая тот факт что обязательных опций может и не быть. + foreach($notRequiredOptions as $notRequiredOption) { + // Если обязательных опцией не оказалось и первая итерация + if(empty($offers)) { + $offers['0:0-0'] = 0; // В случае работы с необязательными опциями мы должны учитывать товарное предложение без опций, поэтому создадим "пустую" опцию + foreach($notRequiredOption['product_option_value'] as $optionValue) { + $offers[$notRequiredOption['product_option_id'].':'.$notRequiredOption['option_id'].'-'.$optionValue['option_value_id']] = (float)$optionValue['price']; + } + } else { + foreach($offers as $optionKey => $optionCost) { + foreach($notRequiredOption['product_option_value'] as $optionValue) { + $offers[$optionKey.'_'.$notRequiredOption['product_option_id'].':'.$notRequiredOption['option_id'].'-'.$optionValue['option_value_id']] = $optionCost + (float)$optionValue['price']; + } + } + } + } + if(empty($offers)) { + $offers = array('0:0-0' => '0'); + } - /** - * Name & price - */ - $e->appendChild($this->dd->createElement('name')) - ->appendChild($this->dd->createTextNode($offer['name'])); - $e->appendChild($this->dd->createElement('productName')) - ->appendChild($this->dd->createTextNode($offer['name'])); - $e->appendChild($this->dd->createElement('price')) - ->appendChild($this->dd->createTextNode($offer['price'])); - - /** - * Vendor - */ - if ($offer['manufacturer_id'] != 0) { - $e->appendChild($this->dd->createElement('vendor')) + foreach($offers as $optionsString => $optionsTotalCost) { + $optionsString = explode('_', $optionsString); + $options = array(); + foreach($optionsString as $optionString) { + $option = explode('-', $optionString); + $optionIds = explode(':', $option[0]); + if($optionString != '0:0-0') { + $optionData = $this->getOptionData($optionIds[1], $option[1]); + $options[$optionIds[0]] = array( + 'name' => $optionData['optionName'], + 'value' => $optionData['optionValue'], + 'value_id' => $option[1] + ); + } + } + ksort($options); + $offerId = array(); + foreach($options as $optionKey => $optionData) { + $offerId[] = $optionKey.'-'.$optionData['value_id']; + } + $offerId = implode('_', $offerId); + $e = $this->eOffers->appendChild($this->dd->createElement('offer')); + if(!empty($offerId)) + $e->setAttribute('id', $product['product_id'].'#'.$offerId); + else + $e->setAttribute('id', $product['product_id']); + $e->setAttribute('productId', $product['product_id']); + $e->setAttribute('quantity', $product['quantity']); + /** + * Offer activity + */ + $activity = $product['status'] == 1 ? 'Y' : 'N'; + $e->appendChild( + $this->dd->createElement('productActivity') + )->appendChild( + $this->dd->createTextNode($activity) + ); + /** + * Offer categories + */ + $categories = $this->model_catalog_product + ->getProductCategories($product['product_id']); + if (!empty($categories)) { + foreach ($categories as $category) { + $e->appendChild($this->dd->createElement('categoryId')) + ->appendChild( + $this->dd->createTextNode($category) + ); + } + } + /** + * Name & price + */ + $e->appendChild($this->dd->createElement('productName')) + ->appendChild($this->dd->createTextNode($product['name'])); + if(!empty($options)) { + $optionsString = array(); + foreach($options as $option) { + $optionsString[] = $option['name'].': '.$option['value']; + } + $optionsString = ' ('.implode(', ', $optionsString).')'; + $e->appendChild($this->dd->createElement('name')) + ->appendChild($this->dd->createTextNode($product['name'].$optionsString)); + } else { + $e->appendChild($this->dd->createElement('name')) + ->appendChild($this->dd->createTextNode($product['name'])); + } + $e->appendChild($this->dd->createElement('price')) + ->appendChild($this->dd->createTextNode($product['price'] + $optionsTotalCost)); + /** + * Vendor + */ + if ($product['manufacturer_id'] != 0) { + $e->appendChild($this->dd->createElement('vendor')) + ->appendChild( + $this->dd->createTextNode( + $offerManufacturers[$product['manufacturer_id']] + ) + ); + } + /** + * Image + */ + if ($product['image']) { + $image = $this->generateImage($product['image']); + $e->appendChild($this->dd->createElement('picture')) + ->appendChild($this->dd->createTextNode($image)); + } + /** + * Url + */ + $this->url = new Url( + HTTP_CATALOG, + $this->config->get('config_secure') + ? HTTP_CATALOG + : HTTPS_CATALOG + ); + $e->appendChild($this->dd->createElement('url')) ->appendChild( $this->dd->createTextNode( - $offerManufacturers[$offer['manufacturer_id']] + $this->url->link( + 'product/product&product_id=' . $product['product_id'] + ) ) ); - } - - /** - * Image - */ - if ($offer['image']) { - $image = $this->generateImage($offer['image']); - $e->appendChild($this->dd->createElement('picture')) - ->appendChild($this->dd->createTextNode($image)); - } - - /** - * Url - */ - $this->url = new Url( - HTTP_CATALOG, - $this->config->get('config_secure') - ? HTTP_CATALOG - : HTTPS_CATALOG - ); - - $e->appendChild($this->dd->createElement('url')) - ->appendChild( - $this->dd->createTextNode( - $this->url->link( - 'product/product&product_id=' . $offer['product_id'] - ) - ) - ); - - - if ($offer['sku']) { - $sku = $this->dd->createElement('param'); - $sku->setAttribute('code', 'article'); - $sku->setAttribute('name', $this->language->get('article')); - $sku->appendChild($this->dd->createTextNode($offer['sku'])); - $e->appendChild($sku); - } - - if ($offer['weight'] != '') { - $weight = $this->dd->createElement('param'); - $weight->setAttribute('code', 'weight'); - $weight->setAttribute('name', $this->language->get('weight')); - $weightValue = (isset($offer['weight_class'])) - ? round($offer['weight'], 3) . ' ' . $offer['weight_class'] - : round($offer['weight'], 3) - ; - $weight->appendChild($this->dd->createTextNode($weightValue)); - $e->appendChild($weight); + // Options + if(!empty($options)) { + foreach($options as $optionKey => $optionData) { + $param = $this->dd->createElement('param'); + $param->setAttribute('code', $optionKey); + $param->setAttribute('name', $optionData['name']); + $param->appendChild($this->dd->createTextNode($optionData['value'])); + $e->appendChild($param); + } + } + if ($product['sku']) { + $sku = $this->dd->createElement('param'); + $sku->setAttribute('code', 'article'); + $sku->setAttribute('name', $this->language->get('article')); + $sku->appendChild($this->dd->createTextNode($product['sku'])); + $e->appendChild($sku); + } + if ($product['weight'] != '') { + $weight = $this->dd->createElement('param'); + $weight->setAttribute('code', 'weight'); + $weight->setAttribute('name', $this->language->get('weight')); + $weightValue = (isset($offer['weight_class'])) + ? round($product['weight'], 3) . ' ' . $product['weight_class'] + : round($product['weight'], 3) + ; + $weight->appendChild($this->dd->createTextNode($weightValue)); + $e->appendChild($weight); + } } } } @@ -226,4 +315,23 @@ class ModelRetailcrmIcml extends Model $this->config->get('config_image_product_height') ); } + + private function getOptionData($optionId, $optionValueId) { + if(!empty($this->options[$optionId])) { + $option = $this->options[$optionId]; + } else { + $option = $this->model_catalog_option->getOption($optionId); + $this->options[$optionId] = $option; + } + if(!empty($this->optionValues[$optionValueId])) { + $optionValue = $this->optionValues[$optionValueId]; + } else { + $optionValue = $this->model_catalog_option->getOptionValue($optionValueId); + $this->optionValues[$optionValueId] = $optionValue; + } + return array( + 'optionName' => $option['name'], + 'optionValue' => $optionValue['name'] + ); + } } diff --git a/catalog/controller/module/retailcrm.php b/catalog/controller/module/retailcrm.php index 089a74f..c2d33b3 100644 --- a/catalog/controller/module/retailcrm.php +++ b/catalog/controller/module/retailcrm.php @@ -25,6 +25,12 @@ class ControllerModuleRetailcrm extends Controller $data = $this->model_checkout_order->getOrder($order_id); $data['products'] = $this->model_account_order->getOrderProducts($order_id); + foreach($data['products'] as $key => $product) { + $productOptions = $this->model_account_order->getOrderOptions($order_id, $product['order_product_id']); + + if(!empty($productOptions)) + $data['products'][$key]['option'] = $productOptions; + } if (!isset($data['fromApi'])) { $this->load->model('setting/setting'); @@ -53,6 +59,13 @@ class ControllerModuleRetailcrm extends Controller $data['products'] = $this->model_account_order->getOrderProducts($order_id); + foreach($data['products'] as $key => $product) { + $productOptions = $this->model_account_order->getOrderOptions($order_id, $product['order_product_id']); + + if(!empty($productOptions)) + $data['products'][$key]['option'] = $productOptions; + } + if (!isset($data['fromApi'])) { $this->load->model('setting/setting'); $status = $this->model_setting_setting->getSetting('retailcrm'); diff --git a/catalog/model/retailcrm/order.php b/catalog/model/retailcrm/order.php index e3fed74..0f6309e 100644 --- a/catalog/model/retailcrm/order.php +++ b/catalog/model/retailcrm/order.php @@ -10,6 +10,8 @@ class ModelRetailcrmOrder extends Model { $settings = $this->model_setting_setting->getSetting('retailcrm'); if(!empty($settings['retailcrm_url']) && !empty($settings['retailcrm_apikey'])) { + $this->load->model('catalog/product'); + require_once DIR_SYSTEM . 'library/retailcrm/bootstrap.php'; $this->retailcrm = new RetailcrmProxy( @@ -29,8 +31,10 @@ class ModelRetailcrmOrder extends Model { 100 ); - foreach($customers['customers'] as $customer) { - $order['customer']['id'] = $customer['id']; + if($customers) { + foreach ($customers['customers'] as $customer) { + $order['customer']['id'] = $customer['id']; + } } unset($customers); @@ -59,14 +63,12 @@ class ModelRetailcrmOrder extends Model { $payment_code = $order_data['payment_code']; $order['paymentType'] = $settings['retailcrm_payment'][$payment_code]; - // Совместимость с 1.5.5, когда этот метод вызывается из model/checkout/order->createOrder(), а не из controller/module/retailcrm->order_create() if(!isset($order_data['shipping_iso_code_2']) && isset($order_data['shipping_country_id'])) { $this->load->model('localisation/country'); $shipping_country = $this->model_localisation_country->getCountry($order_data['shipping_country_id']); $order_data['shipping_iso_code_2'] = $shipping_country['iso_code_2']; } - $delivery_code = $order_data['shipping_code']; $order['delivery'] = array( 'code' => !empty($delivery_code) ? $settings['retailcrm_delivery'][$delivery_code] : '', @@ -87,10 +89,40 @@ class ModelRetailcrmOrder extends Model { ); $orderProducts = isset($order_data['products']) ? $order_data['products'] : $order_data['order_product']; + $offerOptions = array('select', 'radio'); foreach ($orderProducts as $product) { + $offerId = ''; + + if(!empty($product['option'])) { + $options = array(); + + $productOptions = $this->model_catalog_product->getProductOptions($product['product_id']); + + foreach($product['option'] as $option) { + if(!in_array($option['type'], $offerOptions)) continue; + foreach($productOptions as $productOption) { + if($productOption['product_option_id'] = $option['product_option_id']) { + foreach($productOption['product_option_value'] as $productOptionValue) { + if($productOptionValue['product_option_value_id'] == $option['product_option_value_id']) { + $options[$option['product_option_id']] = $productOptionValue['option_value_id']; + } + } + } + } + } + + ksort($options); + + $offerId = array(); + foreach($options as $optionKey => $optionValue) { + $offerId[] = $optionKey.'-'.$optionValue; + } + $offerId = implode('_', $offerId); + } + $order['items'][] = array( - 'productId' => $product['product_id'], + 'productId' => !empty($offerId) ? $product['product_id'].'#'.$offerId : $product['product_id'], 'productName' => $product['name'], 'initialPrice' => $product['price'], 'quantity' => $product['quantity'], @@ -113,6 +145,8 @@ class ModelRetailcrmOrder extends Model { $settings = $this->model_setting_setting->getSetting('retailcrm'); if(!empty($settings['retailcrm_url']) && !empty($settings['retailcrm_apikey'])) { + $this->load->model('catalog/product'); + require_once DIR_SYSTEM . 'library/retailcrm/bootstrap.php'; $this->retailcrm = new RetailcrmProxy( @@ -166,10 +200,40 @@ class ModelRetailcrmOrder extends Model { ); $orderProducts = isset($order_data['products']) ? $order_data['products'] : $order_data['order_product']; + $offerOptions = array('select', 'radio'); foreach ($orderProducts as $product) { + $offerId = ''; + + if(!empty($product['option'])) { + $options = array(); + + $productOptions = $this->model_catalog_product->getProductOptions($product['product_id']); + + foreach($product['option'] as $option) { + if(!in_array($option['type'], $offerOptions)) continue; + foreach($productOptions as $productOption) { + if($productOption['product_option_id'] = $option['product_option_id']) { + foreach($productOption['product_option_value'] as $productOptionValue) { + if($productOptionValue['product_option_value_id'] == $option['product_option_value_id']) { + $options[$option['product_option_id']] = $productOptionValue['option_value_id']; + } + } + } + } + } + + ksort($options); + + $offerId = array(); + foreach($options as $optionKey => $optionValue) { + $offerId[] = $optionKey.'-'.$optionValue; + } + $offerId = implode('_', $offerId); + } + $order['items'][] = array( - 'productId' => $product['product_id'], + 'productId' => !empty($offerId) ? $product['product_id'].'#'.$offerId : $product['product_id'], 'productName' => $product['name'], 'initialPrice' => $product['price'], 'quantity' => $product['quantity'], diff --git a/system/cron/dispatch.php b/system/cron/dispatch.php index 56fba4f..dfd546b 100644 --- a/system/cron/dispatch.php +++ b/system/cron/dispatch.php @@ -68,7 +68,7 @@ foreach ($query->rows as $setting) { if (!$setting['serialized']) { $config->set($setting['key'], $setting['value']); } else { - if (version_compare(VERSION, '2.2', '>=')) + if (version_compare(VERSION, '2.1', '>=')) $config->set($setting['key'], json_decode($setting['value']), true); else $config->set($setting['key'], unserialize($setting['value'])); diff --git a/system/library/retailcrm/OpencartApiClient.php b/system/library/retailcrm/OpencartApiClient.php index 676a5fa..9d1ed37 100644 --- a/system/library/retailcrm/OpencartApiClient.php +++ b/system/library/retailcrm/OpencartApiClient.php @@ -152,7 +152,8 @@ class OpencartApiClient { foreach ($data['order_product'] as $order_product) { $products[] = array( 'product_id' => $order_product['product_id'], - 'quantity' => $order_product['quantity'] + 'quantity' => $order_product['quantity'], + 'option' => $order_product['option'] ); } $this->request('cart/add', array(), array('product' => $products));