diff --git a/retailcrm/config_ru.xml b/retailcrm/config_ru.xml index 6220a7d..d684978 100644 --- a/retailcrm/config_ru.xml +++ b/retailcrm/config_ru.xml @@ -2,7 +2,7 @@ retailcrm - + @@ -10,4 +10,4 @@ 1 1 - + \ No newline at end of file diff --git a/retailcrm/job/export.php b/retailcrm/job/export.php index 8bacdf7..a7b9915 100644 --- a/retailcrm/job/export.php +++ b/retailcrm/job/export.php @@ -7,9 +7,10 @@ require(dirname(__FILE__) . '/../bootstrap.php'); $apiUrl = Configuration::get('RETAILCRM_ADDRESS'); $apiKey = Configuration::get('RETAILCRM_API_TOKEN'); +$apiVersion = Configuration::get('RETAILCRM_API_VERSION'); if (!empty($apiUrl) && !empty($apiKey)) { - $api = new RetailcrmProxy($apiUrl, $apiKey, _PS_ROOT_DIR_ . '/retailcrm.log'); + $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(); @@ -32,7 +33,7 @@ foreach ($customerRecords as $record) { $customers[$record['id_customer']] = array( 'externalId' => $record['id_customer'], 'firstName' => $record['firstname'], - 'lastName' => $record['lastname'], + 'lastname' => $record['lastname'], 'email' => $record['email'] ); } @@ -98,8 +99,17 @@ foreach ($orderRecords as $record) { $order['phone'] = $phone; } - if (array_key_exists($paymentType, $payment)) { - $order['paymentType'] = $payment[$paymentType]; + if ($apiVersion != 5) { + if (array_key_exists($paymentType, $payment)) { + $order['paymentType'] = $payment[$paymentType]; + } + } else { + $order_payment = array( + 'externalId' => $record['id_order'] .'#'. $record['reference'], + 'amount' => $record['total_paid'], + 'type' => $payment[$paymentType] ? $payment[$paymentType] : '' + ); + $order['payments'][] = $order_payment; } if (array_key_exists($record['id_carrier'], $delivery)) { diff --git a/retailcrm/job/missing.php b/retailcrm/job/missing.php index bfd3f73..473ff59 100644 --- a/retailcrm/job/missing.php +++ b/retailcrm/job/missing.php @@ -15,9 +15,10 @@ require(dirname(__FILE__) . '/../bootstrap.php'); $apiUrl = Configuration::get('RETAILCRM_ADDRESS'); $apiKey = Configuration::get('RETAILCRM_API_TOKEN'); +$apiVersion = Configuration::get('RETAILCRM_API_VERSION'); if (!empty($apiUrl) && !empty($apiKey)) { - $api = new RetailcrmProxy($apiUrl, $apiKey, _PS_ROOT_DIR_ . '/retailcrm.log'); + $api = new RetailcrmProxy($apiUrl, $apiKey, _PS_ROOT_DIR_ . '/retailcrm.log', $apiVersion); } else { echo('Set api key & url first'); exit(); diff --git a/retailcrm/job/sync.php b/retailcrm/job/sync.php index 8378a1e..4ba0e0e 100644 --- a/retailcrm/job/sync.php +++ b/retailcrm/job/sync.php @@ -11,16 +11,17 @@ $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'); if (!empty($apiUrl) && !empty($apiKey)) { - $api = new RetailcrmProxy($apiUrl, $apiKey, _PS_ROOT_DIR_ . '/retailcrm.log'); + $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 @@ -55,7 +56,20 @@ if ($history->isSuccessful() && count($history->history) > 0) { $deliveryType = $deliveries[$delivery]; } - $payment = $order['paymentType']; + 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])) { @@ -169,7 +183,7 @@ if ($history->isSuccessful() && count($history->history) > 0) { $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; @@ -204,24 +218,6 @@ if ($history->isSuccessful() && count($history->history) > 0) { $newOrder->total_discounts = $order['discount']; } - $newOrder->add(false, false); - - $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 - */ $product_list = array(); foreach ($order['items'] as $item) { @@ -251,8 +247,55 @@ if ($history->isSuccessful() && count($history->history) > 0) { '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 . '\', + \'' . $orderToUpdate->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`, @@ -333,7 +376,7 @@ if ($history->isSuccessful() && count($history->history) > 0) { /* * check payment type */ - if(!empty($order['paymentType'])) { + if(!empty($order['paymentType']) && $apiVersion != 5) { $ptype = $order['paymentType']; if ($payments[$ptype] != null) { @@ -352,6 +395,39 @@ if ($history->isSuccessful() && count($history->history) > 0) { } } + } 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'] . '\' + )' + ); + } + } + } + } } /* @@ -397,7 +473,7 @@ if ($history->isSuccessful() && count($history->history) > 0) { if ($product_id == $orderItem['product_id'] && $product_attribute_id == $orderItem['product_attribute_id']) { // discount - if (isset($item['discount']) || isset($item['discountPercent'])) { + 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); @@ -412,6 +488,7 @@ if ($history->isSuccessful() && count($history->history) > 0) { $productPrice = $prodPrice - $item['discount']; $productPrice = $productPrice - ($prodPrice / 100 * $item['discountPercent']); + $productPrice = $prodPrice - $item['discountTotal']; $productPrice = round($productPrice , 2); @@ -476,8 +553,9 @@ if ($history->isSuccessful() && count($history->history) > 0) { } // discount - if ($newItem['discount'] || $newItem['discountPercent']) { + if ($newItem['discount'] || $newItem['discountPercent']|| $newItem['discountTotal']) { $productPrice = $productPrice - $newItem['discount']; + $productPrice = $productPrice - $newItem['discountTotal']; $productPrice = $productPrice - ($prodPrice / 100 * $newItem['discountPercent']); $ItemDiscount = true; } @@ -513,6 +591,7 @@ if ($history->isSuccessful() && count($history->history) > 0) { if (isset($order['discount']) || isset($order['discountPercent']) || isset($order['delivery']['cost']) || + isset($order['discountTotal']) || $ItemDiscount) { $infoOrd = $api->ordersGet($order['externalId']); diff --git a/retailcrm/lib/RetailcrmApiClient.php b/retailcrm/lib/RetailcrmApiClientV4.php similarity index 99% rename from retailcrm/lib/RetailcrmApiClient.php rename to retailcrm/lib/RetailcrmApiClientV4.php index f2ddbfb..8009e97 100644 --- a/retailcrm/lib/RetailcrmApiClient.php +++ b/retailcrm/lib/RetailcrmApiClientV4.php @@ -10,9 +10,8 @@ * @license https://opensource.org/licenses/MIT MIT License * @link http://www.retailcrm.ru/docs/Developers/ApiVersion4 */ -class RetailcrmApiClient +class RetailcrmApiClientV4 { - const VERSION = 'v4'; protected $client; diff --git a/retailcrm/lib/RetailcrmApiClientV5.php b/retailcrm/lib/RetailcrmApiClientV5.php new file mode 100644 index 0000000..e5b5d4e --- /dev/null +++ b/retailcrm/lib/RetailcrmApiClientV5.php @@ -0,0 +1,2364 @@ + + * @license https://opensource.org/licenses/MIT MIT License + * @link http://www.retailcrm.ru/docs/Developers/ApiVersion5 + */ +class RetailcrmApiClientV5 +{ + const VERSION = 'v5'; + + protected $client; + + /** + * Site code + */ + protected $siteCode; + + /** + * Client creating + * + * @param string $url api url + * @param string $apiKey api key + * @param string $site site code + * + * @throws \InvalidArgumentException + * + * @return mixed + */ + public function __construct($url, $apiKey, $site = null) + { + if ('/' !== $url[strlen($url) - 1]) { + $url .= '/'; + } + + $url = $url . 'api/' . self::VERSION; + + $this->client = new RetailcrmHttpClient($url, array('apiKey' => $apiKey)); + $this->siteCode = $site; + } + + /** + * Returns users list + * + * @param array $filter + * @param null $page + * @param null $limit + * + * @throws \RetailCrm\Exception\InvalidJsonException + * @throws \RetailCrm\Exception\CurlException + * @throws \InvalidArgumentException + * + * @return ApiResponse + */ + public function usersList(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/users', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Returns user data + * + * @param integer $id user ID + * + * @throws \RetailCrm\Exception\InvalidJsonException + * @throws \RetailCrm\Exception\CurlException + * @throws \InvalidArgumentException + * + * @return ApiResponse + */ + public function usersGet($id) + { + return $this->client->makeRequest("/users/$id", RetailcrmHttpClient::METHOD_GET); + } + + /** + * Change user status + * + * @param integer $id user ID + * @param string $status user status + * + * @return ApiResponse + */ + public function usersStatus($id, $status) + { + $statuses = array("free", "busy", "dinner", "break"); + + if (empty($status) || !in_array($status, $statuses)) { + throw new \InvalidArgumentException( + 'Parameter `status` must be not empty & must be equal one of these values: free|busy|dinner|break' + ); + } + + return $this->client->makeRequest( + "/users/$id/status", + RetailcrmHttpClient::METHOD_POST, + array('status' => $status) + ); + } + + /** + * Get segments list + * + * @param array $filter + * @param null $limit + * @param null $page + * + * @return ApiResponse + */ + public function segmentsList(array $filter = array(), $limit = null, $page = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/segments', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Get custom fields list + * + * @param array $filter + * @param null $limit + * @param null $page + * + * @return ApiResponse + */ + public function customFieldsList(array $filter = array(), $limit = null, $page = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/custom-fields', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Create custom field + * + * @param $entity + * @param $customField + * + * @return ApiResponse + */ + public function customFieldsCreate($entity, $customField) + { + if (!count($customField) || + empty($customField['code']) || + empty($customField['name']) || + empty($customField['type']) + ) { + throw new \InvalidArgumentException( + 'Parameter `customField` must contain a data & fields `code`, `name` & `type` must be set' + ); + } + + if (empty($entity) || $entity != 'customer' || $entity != 'order') { + throw new \InvalidArgumentException( + 'Parameter `entity` must contain a data & value must be `order` or `customer`' + ); + } + + return $this->client->makeRequest( + "/custom-fields/$entity/create", + RetailcrmHttpClient::METHOD_POST, + array('customField' => json_encode($customField)) + ); + } + + /** + * Edit custom field + * + * @param $entity + * @param $customField + * + * @return ApiResponse + */ + public function customFieldsEdit($entity, $customField) + { + if (!count($customField) || empty($customField['code'])) { + throw new \InvalidArgumentException( + 'Parameter `customField` must contain a data & fields `code` must be set' + ); + } + + if (empty($entity) || $entity != 'customer' || $entity != 'order') { + throw new \InvalidArgumentException( + 'Parameter `entity` must contain a data & value must be `order` or `customer`' + ); + } + + return $this->client->makeRequest( + "/custom-fields/$entity/edit/{$customField['code']}", + $this->client::METHOD_POST, + array('customField' => json_encode($customField)) + ); + } + + /** + * Get custom field + * + * @param $entity + * @param $code + * + * @return ApiResponse + */ + public function customFieldsGet($entity, $code) + { + if (empty($code)) { + throw new \InvalidArgumentException( + 'Parameter `code` must be not empty' + ); + } + + if (empty($entity) || $entity != 'customer' || $entity != 'order') { + throw new \InvalidArgumentException( + 'Parameter `entity` must contain a data & value must be `order` or `customer`' + ); + } + + return $this->client->makeRequest( + "/custom-fields/$entity/$code", + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Get custom dictionaries list + * + * @param array $filter + * @param null $limit + * @param null $page + * + * @return ApiResponse + */ + public function customDictionariesList(array $filter = [], $limit = null, $page = null) + { + $parameters = []; + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/custom-fields/dictionaries', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Create custom dictionary + * + * @param $customDictionary + * + * @return ApiResponse + */ + public function customDictionariesCreate($customDictionary) + { + if (!count($customDictionary) || + empty($customDictionary['code']) || + empty($customDictionary['elements']) + ) { + throw new \InvalidArgumentException( + 'Parameter `dictionary` must contain a data & fields `code` & `elemets` must be set' + ); + } + + return $this->client->makeRequest( + "/custom-fields/dictionaries/{$customDictionary['code']}/create", + RetailcrmHttpClient::METHOD_POST, + array('customDictionary' => json_encode($customDictionary)) + ); + } + + /** + * Edit custom dictionary + * + * @param $customDictionary + * + * @return ApiResponse + */ + public function customDictionariesEdit($customDictionary) + { + if (!count($customDictionary) || + empty($customDictionary['code']) || + empty($customDictionary['elements']) + ) { + throw new \InvalidArgumentException( + 'Parameter `dictionary` must contain a data & fields `code` & `elemets` must be set' + ); + } + + return $this->client->makeRequest( + "/custom-fields/dictionaries/{$customDictionary['code']}/edit", + RetailcrmHttpClient::METHOD_POST, + array('customDictionary' => json_encode($customDictionary)) + ); + } + + /** + * Get custom dictionary + * + * @param $code + * + * @return ApiResponse + */ + public function customDictionariesGet($code) + { + if (empty($code)) { + throw new \InvalidArgumentException( + 'Parameter `code` must be not empty' + ); + } + + return $this->client->makeRequest( + "/custom-fields/dictionaries/$code", + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Returns filtered orders list + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersList(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/orders', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Create a order + * + * @param array $order order data + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersCreate(array $order, $site = null) + { + if (!count($order)) { + throw new \InvalidArgumentException( + 'Parameter `order` must contains a data' + ); + } + + return $this->client->makeRequest( + '/orders/create', + RetailcrmHttpClient::METHOD_POST, + $this->fillSite($site, array('order' => json_encode($order))) + ); + } + + /** + * Save order IDs' (id and externalId) association in the CRM + * + * @param array $ids order identificators + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersFixExternalIds(array $ids) + { + if (! count($ids)) { + throw new \InvalidArgumentException( + 'Method parameter must contains at least one IDs pair' + ); + } + + return $this->client->makeRequest( + '/orders/fix-external-ids', + RetailcrmHttpClient::METHOD_POST, + array('orders' => json_encode($ids) + ) + ); + } + + /** + * Returns statuses of the orders + * + * @param array $ids (default: array()) + * @param array $externalIds (default: array()) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersStatuses(array $ids = array(), array $externalIds = array()) + { + $parameters = array(); + + if (count($ids)) { + $parameters['ids'] = $ids; + } + if (count($externalIds)) { + $parameters['externalIds'] = $externalIds; + } + + return $this->client->makeRequest( + '/orders/statuses', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Upload array of the orders + * + * @param array $orders array of orders + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersUpload(array $orders, $site = null) + { + if (!count($orders)) { + throw new \InvalidArgumentException( + 'Parameter `orders` must contains array of the orders' + ); + } + + return $this->client->makeRequest( + '/orders/upload', + RetailcrmHttpClient::METHOD_POST, + $this->fillSite($site, array('orders' => json_encode($orders))) + ); + } + + /** + * Get order by id or externalId + * + * @param string $id order identificator + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersGet($id, $by = 'externalId', $site = null) + { + $this->checkIdParameter($by); + + return $this->client->makeRequest( + "/orders/$id", + RetailcrmHttpClient::METHOD_GET, + $this->fillSite($site, array('by' => $by)) + ); + } + + /** + * Edit a order + * + * @param array $order order data + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersEdit(array $order, $by = 'externalId', $site = null) + { + if (!count($order)) { + throw new \InvalidArgumentException( + 'Parameter `order` must contains a data' + ); + } + + $this->checkIdParameter($by); + + if (!array_key_exists($by, $order)) { + throw new \InvalidArgumentException( + sprintf('Order array must contain the "%s" parameter.', $by) + ); + } + + return $this->client->makeRequest( + sprintf('/orders/%s/edit', $order[$by]), + RetailcrmHttpClient::METHOD_POST, + $this->fillSite( + $site, + array('order' => json_encode($order), 'by' => $by) + ) + ); + } + + /** + * Get orders history + * @param array $filter + * @param null $page + * @param null $limit + * + * @return ApiResponse + */ + public function ordersHistory(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/orders/history', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Combine orders + * + * @param string $technique + * @param array $order + * @param array $resultOrder + * + * @return ApiResponse + */ + public function ordersCombine($order, $resultOrder, $technique = 'ours') + { + $techniques = array('ours', 'summ', 'theirs'); + + if (!count($order) || !count($resultOrder)) { + throw new \InvalidArgumentException( + 'Parameters `order` & `resultOrder` must contains a data' + ); + } + + if (!in_array($technique, $techniques)) { + throw new \InvalidArgumentException( + 'Parameter `technique` must be on of ours|summ|theirs' + ); + } + + return $this->client->makeRequest( + '/orders/combine', + RetailcrmHttpClient::METHOD_POST, + array( + 'technique' => $technique, + 'order' => json_encode($order), + 'resultOrder' => json_encode($resultOrder) + ) + ); + } + + /** + * Create an order payment + * + * @param array $payment order data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersPaymentCreate(array $payment) + { + if (!count($payment)) { + throw new \InvalidArgumentException( + 'Parameter `payment` must contains a data' + ); + } + + return $this->client->makeRequest( + '/orders/payments/create', + RetailcrmHttpClient::METHOD_POST, + array('payment' => json_encode($payment)) + ); + } + + /** + * Edit an order payment + * + * @param array $payment order data + * @param string $by by key + * @param null $site site code + * + * @return ApiResponse + */ + public function ordersPaymentEdit(array $payment, $by = 'externalId', $site = null) + { + if (!count($payment)) { + throw new \InvalidArgumentException( + 'Parameter `payment` must contains a data' + ); + } + + $this->checkIdParameter($by); + + if (!array_key_exists($by, $payment)) { + throw new \InvalidArgumentException( + sprintf('Order array must contain the "%s" parameter.', $by) + ); + } + + return $this->client->makeRequest( + sprintf('/orders/payments/%s/edit', $payment[$by]), + RetailcrmHttpClient::METHOD_POST, + $this->fillSite( + $site, + array('payment' => json_encode($payment), 'by' => $by) + ) + ); + } + + /** + * Edit an order payment + * + * @param string $id payment id + * + * @return ApiResponse + */ + public function ordersPaymentDelete($id) + { + if (!$id) { + throw new \InvalidArgumentException( + 'Parameter `id` must be set' + ); + } + + return $this->client->makeRequest( + sprintf('/orders/payments/%s/delete', $id), + RetailcrmHttpClient::METHOD_POST + ); + } + + /** + * Returns filtered customers list + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersList(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/customers', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Create a customer + * + * @param array $customer customer data + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersCreate(array $customer, $site = null) + { + if (! count($customer)) { + throw new \InvalidArgumentException( + 'Parameter `customer` must contains a data' + ); + } + + return $this->client->makeRequest( + '/customers/create', + RetailcrmHttpClient::METHOD_POST, + $this->fillSite($site, array('customer' => json_encode($customer))) + ); + } + + /** + * Save customer IDs' (id and externalId) association in the CRM + * + * @param array $ids ids mapping + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersFixExternalIds(array $ids) + { + if (! count($ids)) { + throw new \InvalidArgumentException( + 'Method parameter must contains at least one IDs pair' + ); + } + + return $this->client->makeRequest( + '/customers/fix-external-ids', + RetailcrmHttpClient::METHOD_POST, + array('customers' => json_encode($ids)) + ); + } + + /** + * Upload array of the customers + * + * @param array $customers array of customers + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersUpload(array $customers, $site = null) + { + if (! count($customers)) { + throw new \InvalidArgumentException( + 'Parameter `customers` must contains array of the customers' + ); + } + + return $this->client->makeRequest( + '/customers/upload', + RetailcrmHttpClient::METHOD_POST, + $this->fillSite($site, array('customers' => json_encode($customers))) + ); + } + + /** + * Get customer by id or externalId + * + * @param string $id customer identificator + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersGet($id, $by = 'externalId', $site = null) + { + $this->checkIdParameter($by); + + return $this->client->makeRequest( + "/customers/$id", + RetailcrmHttpClient::METHOD_GET, + $this->fillSite($site, array('by' => $by)) + ); + } + + /** + * Edit a customer + * + * @param array $customer customer data + * @param string $by (default: 'externalId') + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersEdit(array $customer, $by = 'externalId', $site = null) + { + if (!count($customer)) { + throw new \InvalidArgumentException( + 'Parameter `customer` must contains a data' + ); + } + + $this->checkIdParameter($by); + + if (!array_key_exists($by, $customer)) { + throw new \InvalidArgumentException( + sprintf('Customer array must contain the "%s" parameter.', $by) + ); + } + + return $this->client->makeRequest( + sprintf('/customers/%s/edit', $customer[$by]), + RetailcrmHttpClient::METHOD_POST, + $this->fillSite( + $site, + array('customer' => json_encode($customer), 'by' => $by) + ) + ); + } + + /** + * Get customers history + * @param array $filter + * @param null $page + * @param null $limit + * + * @return ApiResponse + */ + public function customersHistory(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/customers/history', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Combine customers + * + * @param array $customers + * @param array $resultCustomer + * + * @return ApiResponse + */ + public function customersCombine(array $customers, $resultCustomer) + { + + if (!count($customers) || !count($resultCustomer)) { + throw new \InvalidArgumentException( + 'Parameters `customers` & `resultCustomer` must contains a data' + ); + } + + return $this->client->makeRequest( + '/customers/combine', + RetailcrmHttpClient::METHOD_POST, + array( + 'customers' => json_encode($customers), + 'resultCustomer' => json_encode($resultCustomer) + ) + ); + } + + /** + * Returns filtered customers notes list + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersNotesList(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + return $this->client->makeRequest( + '/customers/notes', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Create customer note + * + * @param array $note (default: array()) + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersNotesCreate($note, $site = null) + { + if (empty($note['customer']['id']) && empty($note['customer']['externalId'])) { + throw new \InvalidArgumentException( + 'Customer identifier must be set' + ); + } + return $this->client->makeRequest( + '/customers/notes/create', + RetailcrmHttpClient::METHOD_POST, + $this->fillSite($site, array('note' => json_encode($note))) + ); + } + + /** + * Delete customer note + * + * @param integer $id + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function customersNotesDelete($id) + { + if (empty($id)) { + throw new \InvalidArgumentException( + 'Note id must be set' + ); + } + return $this->client->makeRequest( + "/customers/notes/$id/delete", + RetailcrmHttpClient::METHOD_POST + ); + } + + /** + * Get orders assembly list + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersPacksList(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/orders/packs', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Create orders assembly + * + * @param array $pack pack data + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersPacksCreate(array $pack, $site = null) + { + if (!count($pack)) { + throw new \InvalidArgumentException( + 'Parameter `pack` must contains a data' + ); + } + + return $this->client->makeRequest( + '/orders/packs/create', + RetailcrmHttpClient::METHOD_POST, + $this->fillSite($site, array('pack' => json_encode($pack))) + ); + } + + /** + * Get orders assembly history + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersPacksHistory(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/orders/packs/history', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Get orders assembly by id + * + * @param string $id pack identificator + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersPacksGet($id) + { + if (empty($id)) { + throw new \InvalidArgumentException('Parameter `id` must be set'); + } + + return $this->client->makeRequest( + "/orders/packs/$id", + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Delete orders assembly by id + * + * @param string $id pack identificator + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersPacksDelete($id) + { + if (empty($id)) { + throw new \InvalidArgumentException('Parameter `id` must be set'); + } + + return $this->client->makeRequest( + sprintf('/orders/packs/%s/delete', $id), + RetailcrmHttpClient::METHOD_POST + ); + } + + /** + * Edit orders assembly + * + * @param array $pack pack data + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function ordersPacksEdit(array $pack, $site = null) + { + if (!count($pack) || empty($pack['id'])) { + throw new \InvalidArgumentException( + 'Parameter `pack` must contains a data & pack `id` must be set' + ); + } + + return $this->client->makeRequest( + sprintf('/orders/packs/%s/edit', $pack['id']), + RetailcrmHttpClient::METHOD_POST, + $this->fillSite($site, array('pack' => json_encode($pack))) + ); + } + + /** + * Get tasks list + * + * @param array $filter + * @param null $limit + * @param null $page + * + * @return ApiResponse + */ + public function tasksList(array $filter = array(), $limit = null, $page = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/tasks', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Create task + * + * @param array $task + * @param null $site + * + * @return ApiResponse + * + */ + public function tasksCreate($task, $site = null) + { + if (!count($task)) { + throw new \InvalidArgumentException( + 'Parameter `task` must contain a data' + ); + } + + return $this->client->makeRequest( + "/tasks/create", + RetailcrmHttpClient::METHOD_POST, + $this->fillSite( + $site, + array('task' => json_encode($task)) + ) + ); + } + + /** + * Edit task + * + * @param array $task + * @param null $site + * + * @return ApiResponse + * + */ + public function tasksEdit($task, $site = null) + { + if (!count($task)) { + throw new \InvalidArgumentException( + 'Parameter `task` must contain a data' + ); + } + + return $this->client->makeRequest( + "/tasks/{$task['id']}/edit", + RetailcrmHttpClient::METHOD_POST, + $this->fillSite( + $site, + array('task' => json_encode($task)) + ) + ); + } + + /** + * Get custom dictionary + * + * @param $id + * + * @return ApiResponse + */ + public function tasksGet($id) + { + if (empty($id)) { + throw new \InvalidArgumentException( + 'Parameter `id` must be not empty' + ); + } + + return $this->client->makeRequest( + "/tasks/$id", + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Get products groups + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function storeProductsGroups(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/store/product-groups', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Get purchace prices & stock balance + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function storeInventories(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/store/inventories', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Get store settings + * + * @param string $code get settings code + * + * @return ApiResponse + * @throws \RetailCrm\Exception\InvalidJsonException + * @throws \RetailCrm\Exception\CurlException + * @throws \InvalidArgumentException + * + * @return ApiResponse + */ + public function storeSettingsGet($code) + { + if (empty($code)) { + throw new \InvalidArgumentException('Parameter `code` must be set'); + } + + return $this->client->makeRequest( + "/store/setting/$code", + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit store configuration + * + * @param array $configuration + * + * @throws \RetailCrm\Exception\InvalidJsonException + * @throws \RetailCrm\Exception\CurlException + * @throws \InvalidArgumentException + * + * @return ApiResponse + */ + public function storeSettingsEdit(array $configuration) + { + if (!count($configuration) || empty($configuration['code'])) { + throw new \InvalidArgumentException( + 'Parameter `configuration` must contains a data & configuration `code` must be set' + ); + } + + return $this->client->makeRequest( + sprintf('/store/setting/%s/edit', $configuration['code']), + RetailcrmHttpClient::METHOD_POST, + $configuration + ); + } + + /** + * Upload store inventories + * + * @param array $offers offers data + * @param string $site (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function storeInventoriesUpload(array $offers, $site = null) + { + if (!count($offers)) { + throw new \InvalidArgumentException( + 'Parameter `offers` must contains array of the offers' + ); + } + + return $this->client->makeRequest( + '/store/inventories/upload', + RetailcrmHttpClient::METHOD_POST, + $this->fillSite($site, array('offers' => json_encode($offers))) + ); + } + + /** + * Get products + * + * @param array $filter (default: array()) + * @param int $page (default: null) + * @param int $limit (default: null) + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function storeProducts(array $filter = array(), $page = null, $limit = null) + { + $parameters = array(); + + if (count($filter)) { + $parameters['filter'] = $filter; + } + if (null !== $page) { + $parameters['page'] = (int) $page; + } + if (null !== $limit) { + $parameters['limit'] = (int) $limit; + } + + return $this->client->makeRequest( + '/store/products', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Get delivery settings + * + * @param string $code + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function deliverySettingsGet($code) + { + if (empty($code)) { + throw new \InvalidArgumentException('Parameter `code` must be set'); + } + + return $this->client->makeRequest( + "/delivery/generic/setting/$code", + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit delivery configuration + * + * @param array $configuration + * + * @throws \RetailCrm\Exception\InvalidJsonException + * @throws \RetailCrm\Exception\CurlException + * @throws \InvalidArgumentException + * + * @return ApiResponse + */ + public function deliverySettingsEdit(array $configuration) + { + if (!count($configuration) || empty($configuration['code'])) { + throw new \InvalidArgumentException( + 'Parameter `configuration` must contains a data & configuration `code` must be set' + ); + } + + return $this->client->makeRequest( + sprintf('/delivery/generic/setting/%s/edit', $configuration['code']), + RetailcrmHttpClient::METHOD_POST, + array('configuration' => json_encode($configuration)) + ); + } + + /** + * Delivery tracking update + * + * @param string $code + * @param array $statusUpdate + * + * @throws \RetailCrm\Exception\InvalidJsonException + * @throws \RetailCrm\Exception\CurlException + * @throws \InvalidArgumentException + * + * @return ApiResponse + */ + public function deliveryTracking($code, array $statusUpdate) + { + if (empty($code)) { + throw new \InvalidArgumentException('Parameter `code` must be set'); + } + + if (!count($statusUpdate)) { + throw new \InvalidArgumentException( + 'Parameter `statusUpdate` must contains a data' + ); + } + + return $this->client->makeRequest( + sprintf('/delivery/generic/%s/tracking', $code), + RetailcrmHttpClient::METHOD_POST, + $statusUpdate + ); + } + + /** + * Returns available county list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function countriesList() + { + return $this->client->makeRequest( + '/reference/countries', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Returns deliveryServices list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function deliveryServicesList() + { + return $this->client->makeRequest( + '/reference/delivery-services', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit deliveryService + * + * @param array $data delivery service data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function deliveryServicesEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/delivery-services/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('deliveryService' => json_encode($data)) + ); + } + + /** + * Returns deliveryTypes list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function deliveryTypesList() + { + return $this->client->makeRequest( + '/reference/delivery-types', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit deliveryType + * + * @param array $data delivery type data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function deliveryTypesEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/delivery-types/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('deliveryType' => json_encode($data)) + ); + } + + /** + * Returns orderMethods list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function orderMethodsList() + { + return $this->client->makeRequest( + '/reference/order-methods', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit orderMethod + * + * @param array $data order method data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function orderMethodsEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/order-methods/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('orderMethod' => json_encode($data)) + ); + } + + /** + * Returns orderTypes list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function orderTypesList() + { + return $this->client->makeRequest( + '/reference/order-types', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit orderType + * + * @param array $data order type data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function orderTypesEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/order-types/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('orderType' => json_encode($data)) + ); + } + + /** + * Returns paymentStatuses list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function paymentStatusesList() + { + return $this->client->makeRequest( + '/reference/payment-statuses', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit paymentStatus + * + * @param array $data payment status data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function paymentStatusesEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/payment-statuses/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('paymentStatus' => json_encode($data)) + ); + } + + /** + * Returns paymentTypes list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function paymentTypesList() + { + return $this->client->makeRequest( + '/reference/payment-types', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit paymentType + * + * @param array $data payment type data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function paymentTypesEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/payment-types/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('paymentType' => json_encode($data)) + ); + } + + /** + * Returns productStatuses list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function productStatusesList() + { + return $this->client->makeRequest( + '/reference/product-statuses', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit productStatus + * + * @param array $data product status data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function productStatusesEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/product-statuses/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('productStatus' => json_encode($data)) + ); + } + + /** + * Returns sites list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function sitesList() + { + return $this->client->makeRequest( + '/reference/sites', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit site + * + * @param array $data site data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function sitesEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/sites/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('site' => json_encode($data)) + ); + } + + /** + * Returns statusGroups list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function statusGroupsList() + { + return $this->client->makeRequest( + '/reference/status-groups', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Returns statuses list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function statusesList() + { + return $this->client->makeRequest( + '/reference/statuses', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit order status + * + * @param array $data status data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function statusesEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/statuses/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('status' => json_encode($data)) + ); + } + + /** + * Returns stores list + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function storesList() + { + return $this->client->makeRequest( + '/reference/stores', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit store + * + * @param array $data site data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function storesEdit(array $data) + { + if (!array_key_exists('code', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "code" parameter.' + ); + } + + if (!array_key_exists('name', $data)) { + throw new \InvalidArgumentException( + 'Data must contain "name" parameter.' + ); + } + + return $this->client->makeRequest( + sprintf('/reference/stores/%s/edit', $data['code']), + RetailcrmHttpClient::METHOD_POST, + array('store' => json_encode($data)) + ); + } + + /** + * Get telephony settings + * + * @param string $code + * + * @throws \RetailCrm\Exception\InvalidJsonException + * @throws \RetailCrm\Exception\CurlException + * @throws \InvalidArgumentException + * + * @return ApiResponse + */ + public function telephonySettingsGet($code) + { + if (empty($code)) { + throw new \InvalidArgumentException('Parameter `code` must be set'); + } + + return $this->client->makeRequest( + "/telephony/setting/$code", + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Edit telephony settings + * + * @param string $code symbolic code + * @param string $clientId client id + * @param boolean $active telephony activity + * @param mixed $name service name + * @param mixed $makeCallUrl service init url + * @param mixed $image service logo url(svg file) + * + * @param array $additionalCodes + * @param array $externalPhones + * @param bool $allowEdit + * @param bool $inputEventSupported + * @param bool $outputEventSupported + * @param bool $hangupEventSupported + * @param bool $changeUserStatusUrl + * + * @return ApiResponse + */ + public function telephonySettingsEdit( + $code, + $clientId, + $active = false, + $name = false, + $makeCallUrl = false, + $image = false, + $additionalCodes = array(), + $externalPhones = array(), + $allowEdit = false, + $inputEventSupported = false, + $outputEventSupported = false, + $hangupEventSupported = false, + $changeUserStatusUrl = false + ) + { + if (!isset($code)) { + throw new \InvalidArgumentException('Code must be set'); + } + + $parameters['code'] = $code; + + if (!isset($clientId)) { + throw new \InvalidArgumentException('client id must be set'); + } + + $parameters['clientId'] = $clientId; + + if (!isset($active)) { + $parameters['active'] = false; + } else { + $parameters['active'] = $active; + } + + if (!isset($name)) { + throw new \InvalidArgumentException('name must be set'); + } + + if (isset($name)) { + $parameters['name'] = $name; + } + + if (isset($makeCallUrl)) { + $parameters['makeCallUrl'] = $makeCallUrl; + } + + if (isset($image)) { + $parameters['image'] = $image; + } + + if (isset($additionalCodes)) { + $parameters['additionalCodes'] = $additionalCodes; + } + + if (isset($externalPhones)) { + $parameters['externalPhones'] = $externalPhones; + } + + if (isset($allowEdit)) { + $parameters['allowEdit'] = $allowEdit; + } + + if (isset($inputEventSupported)) { + $parameters['inputEventSupported'] = $inputEventSupported; + } + + if (isset($outputEventSupported)) { + $parameters['outputEventSupported'] = $outputEventSupported; + } + + if (isset($hangupEventSupported)) { + $parameters['hangupEventSupported'] = $hangupEventSupported; + } + + if (isset($changeUserStatusUrl)) { + $parameters['changeUserStatusUrl'] = $changeUserStatusUrl; + } + + return $this->client->makeRequest( + "/telephony/setting/$code/edit", + RetailcrmHttpClient::METHOD_POST, + array('configuration' => json_encode($parameters)) + ); + } + + /** + * Call event + * + * @param string $phone phone number + * @param string $type call type + * @param array $codes + * @param string $hangupStatus + * @param string $externalPhone + * @param array $webAnalyticsData + * + * @return ApiResponse + * @internal param string $code additional phone code + * @internal param string $status call status + * + */ + public function telephonyCallEvent( + $phone, + $type, + $codes, + $hangupStatus, + $externalPhone = null, + $webAnalyticsData = array() + ) + { + if (!isset($phone)) { + throw new \InvalidArgumentException('Phone number must be set'); + } + + if (!isset($type)) { + throw new \InvalidArgumentException('Type must be set (in|out|hangup)'); + } + + if (empty($codes)) { + throw new \InvalidArgumentException('Codes array must be set'); + } + + $parameters['phone'] = $phone; + $parameters['type'] = $type; + $parameters['codes'] = $codes; + $parameters['hangupStatus'] = $hangupStatus; + $parameters['callExternalId'] = $externalPhone; + $parameters['webAnalyticsData'] = $webAnalyticsData; + + + return $this->client->makeRequest( + '/telephony/call/event', + RetailcrmHttpClient::METHOD_POST, + array('event' => json_encode($parameters)) + ); + } + + /** + * Upload calls + * + * @param array $calls calls data + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function telephonyCallsUpload(array $calls) + { + if (!count($calls)) { + throw new \InvalidArgumentException( + 'Parameter `calls` must contains array of the calls' + ); + } + + return $this->client->makeRequest( + '/telephony/calls/upload', + RetailcrmHttpClient::METHOD_POST, + array('calls' => json_encode($calls)) + ); + } + + /** + * Get call manager + * + * @param string $phone phone number + * @param bool $details detailed information + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function telephonyCallManager($phone, $details) + { + if (!isset($phone)) { + throw new \InvalidArgumentException('Phone number must be set'); + } + + $parameters['phone'] = $phone; + $parameters['details'] = isset($details) ? $details : 0; + + return $this->client->makeRequest( + '/telephony/manager', + RetailcrmHttpClient::METHOD_GET, + $parameters + ); + } + + /** + * Update CRM basic statistic + * + * @throws \InvalidArgumentException + * @throws \RetailCrm\Exception\CurlException + * @throws \RetailCrm\Exception\InvalidJsonException + * + * @return ApiResponse + */ + public function statisticUpdate() + { + return $this->client->makeRequest( + '/statistic/update', + RetailcrmHttpClient::METHOD_GET + ); + } + + /** + * Return current site + * + * @return string + */ + public function getSite() + { + return $this->siteCode; + } + + /** + * Set site + * + * @param string $site site code + * + * @return void + */ + public function setSite($site) + { + $this->siteCode = $site; + } + + /** + * Check ID parameter + * + * @param string $by identify by + * + * @throws \InvalidArgumentException + * + * @return bool + */ + protected function checkIdParameter($by) + { + $allowedForBy = array( + 'externalId', + 'id' + ); + + if (!in_array($by, $allowedForBy, false)) { + throw new \InvalidArgumentException( + sprintf( + 'Value "%s" for "by" param is not valid. Allowed values are %s.', + $by, + implode(', ', $allowedForBy) + ) + ); + } + + return true; + } + + /** + * Fill params by site value + * + * @param string $site site code + * @param array $params input parameters + * + * @return array + */ + protected function fillSite($site, array $params) + { + if ($site) { + $params['site'] = $site; + } elseif ($this->siteCode) { + $params['site'] = $this->siteCode; + } + + return $params; + } +} diff --git a/retailcrm/lib/RetailcrmCatalog.php b/retailcrm/lib/RetailcrmCatalog.php index bc55518..2414979 100644 --- a/retailcrm/lib/RetailcrmCatalog.php +++ b/retailcrm/lib/RetailcrmCatalog.php @@ -26,7 +26,7 @@ class RetailcrmCatalog $currencies = Currency::getCurrencies(); - $types = Category::getCategories($id_lang, false, false); + $types = Category::getCategories($id_lang, true, false); foreach ($types AS $category) { $categories[] = array( 'id' => $category['id_category'], @@ -106,9 +106,9 @@ class RetailcrmCatalog } else { $size = null; } - - $productForCombination = new Product($product['id_product']); - + + $productForCombination = new Product($product['id_product']); + $offers = Product::getProductAttributesIds($product['id_product']); if(!empty($offers)) { @@ -116,7 +116,7 @@ class RetailcrmCatalog $combinations = $productForCombination->getAttributeCombinationsById($offer['id_product_attribute' ], $id_lang); if (!empty($combinations)) { - + foreach ($combinations as $combination) { $arSet = array( 'group_name' => $combination['group_name'], @@ -126,11 +126,6 @@ class RetailcrmCatalog } } - if (!empty($combinations[0]['reference'])) { - $articleCombination = $combinations[0]['reference']; - } else { - $articleCombination = null; - } $pictures = array(); $covers = Image::getImages($id_lang, $product['id_product'], $offer['id_product_attribute']); foreach($covers as $cover) { @@ -145,8 +140,7 @@ class RetailcrmCatalog } $offerPrice = Combination::getPrice($offer['id_product_attribute']); - //$offerPrice = $offerPrice > 0 ? $offerPrice : $price; - $offerPrice = $offerPrice != 0 ? $offerPrice + $price : $price; + $offerPrice = $offerPrice > 0 ? $offerPrice : $price; $item = array( 'id' => $product['id_product'] . '#' . $offer['id_product_attribute'], @@ -161,12 +155,9 @@ class RetailcrmCatalog 'purchasePrice' => $purchasePrice, 'price' => round($offerPrice, 2), 'vendor' => $vendor, - 'article' => ($articleCombination) ? $articleCombination : $article, + 'article' => $article, 'weight' => $weight, - 'size' => $size, - 'width' => $width, - 'height' => $height, - 'depth' => $depth + 'size' => $size ); if (!empty($combinations)) { @@ -174,7 +165,7 @@ class RetailcrmCatalog $item[mb_strtolower($itemComb['group_name'])] = htmlspecialchars($itemComb['attribute']); } } - + $items[] = $item; } } else { @@ -206,10 +197,7 @@ class RetailcrmCatalog 'vendor' => $vendor, 'article' => $article, 'weight' => $weight, - 'size' => $size, - 'width' => $width, - 'height' => $height, - 'depth' => $depth + 'size' => $size ); $items[] = $item; diff --git a/retailcrm/lib/RetailcrmHistoryHelper.php b/retailcrm/lib/RetailcrmHistoryHelper.php index 03a330d..8882f85 100644 --- a/retailcrm/lib/RetailcrmHistoryHelper.php +++ b/retailcrm/lib/RetailcrmHistoryHelper.php @@ -33,7 +33,24 @@ class RetailcrmHistoryHelper { } else { $orders[$change['order']['id']] = $change['order']; } - + + if($change['payment']) { + if($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') { + $orders[$change['order']['id']]['payments'][$change['payment']['id']]['create'] = true; + } + 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']]) { + $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']]) { $orders[$change['order']['id']]['items'][$change['item']['id']] = array_merge($orders[$change['order']['id']]['items'][$change['item']['id']], $change['item']); @@ -65,6 +82,8 @@ class RetailcrmHistoryHelper { $orders[$change['order']['id']]['customFields'][str_replace('custom_', '', $change['field'])] = self::newValue($change['newValue']); } elseif($fields['order'][$change['field']]) { $orders[$change['order']['id']][$fields['order'][$change['field']]] = self::newValue($change['newValue']); + } elseif($fields['payment'][$change['field']]) { + $orders[$change['order']['id']]['payments'][$change['payment']['id']][$fields['payment'][$change['field']]] = self::newValue($change['newValue']); } if(isset($change['created'])) { diff --git a/retailcrm/lib/RetailcrmIcml.php b/retailcrm/lib/RetailcrmIcml.php index 7dd540c..8c72447 100644 --- a/retailcrm/lib/RetailcrmIcml.php +++ b/retailcrm/lib/RetailcrmIcml.php @@ -33,10 +33,7 @@ class RetailcrmIcml 'color' => 'Цвет', 'weight' => 'Вес', 'size' => 'Размер', - 'tax' => 'Наценка', - 'width' => 'Ширина', - 'height' => 'Высота', - 'depth' => 'Глубина' + 'tax' => 'Наценка' ); } @@ -78,14 +75,14 @@ class RetailcrmIcml foreach ($categories as $category) { $e = $this->eCategories->appendChild( $this->dd->createElement( - 'category', htmlspecialchars($category['name']) + 'category', $category['name'] ) ); $e->setAttribute('id', $category['id']); if ($category['parentId'] > 0) { - $e->setAttribute('parentId', htmlspecialchars($category['parentId'])); + $e->setAttribute('parentId', $category['parentId']); } } } diff --git a/retailcrm/lib/RetailcrmProxy.php b/retailcrm/lib/RetailcrmProxy.php index f99f740..ab988c9 100644 --- a/retailcrm/lib/RetailcrmProxy.php +++ b/retailcrm/lib/RetailcrmProxy.php @@ -6,23 +6,34 @@ */ class RetailcrmProxy { - private $api; private $log; - public function __construct($url, $key, $log) - { - $this->api = new RetailcrmApiClient($url, $key); + public function __construct($url, $key, $log, $version = '4') + { + switch ($version) { + case '5': + $this->api = new RetailcrmApiClientV5($url, $key); + break; + case '4': + $this->api = new RetailcrmApiClientV4($url, $key); + break; + case '3': + $this->api = new RetailcrmApiClientV3($url, $key); + break; + } + $this->log = $log; } public function __call($method, $arguments) - { + { + $date = date('Y-m-d H:i:s'); try { $response = call_user_func_array(array($this->api, $method), $arguments); if (!$response->isSuccessful()) { - error_log("[$method] " . $response->getErrorMsg() . "\n", 3, $this->log); + error_log("[$date] @ [$method] " . $response->getErrorMsg() . "\n", 3, $this->log); if (isset($response['errors'])) { $error = implode("\n", $response['errors']); error_log($error . "\n", 3, $this->log); @@ -32,10 +43,10 @@ class RetailcrmProxy return $response; } catch (CurlException $e) { - error_log("[$method] " . $e->getMessage() . "\n", 3, $this->log); + error_log("[$date] @ [$method] " . $e->getMessage() . "\n", 3, $this->log); return false; } catch (InvalidJsonException $e) { - error_log("[$method] " . $e->getMessage() . "\n", 3, $this->log); + error_log("[$date] @ [$method] " . $e->getMessage() . "\n", 3, $this->log); return false; } } diff --git a/retailcrm/lib/RetailcrmReferences.php b/retailcrm/lib/RetailcrmReferences.php index 4a16459..ab8eed7 100644 --- a/retailcrm/lib/RetailcrmReferences.php +++ b/retailcrm/lib/RetailcrmReferences.php @@ -94,7 +94,7 @@ class RetailcrmReferences return $paymentTypes; } -public function getPaymentAndDeliveryForDefault($arParams) + public function getPaymentAndDeliveryForDefault($arParams) { $paymentTypes = array(); $deliveryTypes = array(); @@ -158,7 +158,7 @@ public function getPaymentAndDeliveryForDefault($arParams) return $paymentDeliveryTypes; } - protected function getSystemPaymentModules() + public function getSystemPaymentModules() { $shop_id = Context::getContext()->shop->id; diff --git a/retailcrm/objects.xml b/retailcrm/objects.xml index 4f4996e..5b98ab5 100644 --- a/retailcrm/objects.xml +++ b/retailcrm/objects.xml @@ -63,7 +63,10 @@ shipmentDate shipped - + payments + amount + status + id initialPrice discount diff --git a/retailcrm/retailcrm.php b/retailcrm/retailcrm.php index 60f58b6..327e760 100644 --- a/retailcrm/retailcrm.php +++ b/retailcrm/retailcrm.php @@ -20,7 +20,8 @@ class RetailCRM extends Module { $this->name = 'retailcrm'; $this->tab = 'export'; - $this->version = '2.2'; + $this->version = '2.1.1'; + $this->version = '2.1'; $this->author = 'Retail Driver LCC'; $this->displayName = $this->l('RetailCRM'); $this->description = $this->l('Integration module for RetailCRM'); @@ -30,16 +31,18 @@ class RetailCRM extends Module $this->default_country = (int)Configuration::get('PS_COUNTRY_DEFAULT'); $this->apiUrl = Configuration::get('RETAILCRM_ADDRESS'); $this->apiKey = Configuration::get('RETAILCRM_API_TOKEN'); + $this->apiVersion = Configuration::get('RETAILCRM_API_VERSION'); $this->ps_versions_compliancy = array('min' => '1.5', 'max' => _PS_VERSION_); $this->version = substr(_PS_VERSION_, 0, 3); + $this->log = _PS_ROOT_DIR_ . '/retailcrm.log'; if ($this->version == '1.6') { $this->bootstrap = true; $this->use_new_hooks = false; } - if ($this->validateCrmAddress($this->apiUrl) && !empty($this->apiKey)) { - $this->api = new RetailcrmProxy($this->apiUrl, $this->apiKey, _PS_ROOT_DIR_ . '/retailcrm.log'); + if ($this->apiUrl && $this->apiKey) { + $this->api = new RetailcrmProxy($this->apiUrl, $this->apiKey, $this->log, $this->apiVersion); $this->reference = new RetailcrmReferences($this->api); } @@ -66,32 +69,39 @@ class RetailCRM extends Module Configuration::deleteByName('RETAILCRM_API_TOKEN') && Configuration::deleteByName('RETAILCRM_API_STATUS') && Configuration::deleteByName('RETAILCRM_API_DELIVERY') && - Configuration::deleteByName('RETAILCRM_LAST_SYNC'); + Configuration::deleteByName('RETAILCRM_LAST_SYNC') && + Configuration::deleteByName('RETAILCRM_API_VERSION'); } public function getContent() - { + { $output = null; $address = Configuration::get('RETAILCRM_ADDRESS'); $token = Configuration::get('RETAILCRM_API_TOKEN'); + $version = Configuration::get('RETAILCRM_API_VERSION'); if (Tools::isSubmit('submit' . $this->name)) { $address = strval(Tools::getValue('RETAILCRM_ADDRESS')); $token = strval(Tools::getValue('RETAILCRM_API_TOKEN')); + $version = strval(Tools::getValue('RETAILCRM_API_VERSION')); $delivery = json_encode(Tools::getValue('RETAILCRM_API_DELIVERY')); $status = json_encode(Tools::getValue('RETAILCRM_API_STATUS')); $payment = json_encode(Tools::getValue('RETAILCRM_API_PAYMENT')); $deliveryDefault = json_encode(Tools::getValue('RETAILCRM_API_DELIVERY_DEFAULT')); $paymentDefault = json_encode(Tools::getValue('RETAILCRM_API_PAYMENT_DEFAULT')); + $settings = array( + 'address' => $address, + 'token' => $token, + 'version' => $version + ); - if (!$this->validateCrmAddress($address) || !Validate::isGenericName($address)) { - $output .= $this->displayError($this->l('Invalid crm address')); - } elseif (!$token || empty($token) || !Validate::isGenericName($token)) { - $output .= $this->displayError($this->l('Invalid crm api token')); - } else { + $output .= $this->validateForm($settings, $output); + + if ($output === '') { Configuration::updateValue('RETAILCRM_ADDRESS', $address); Configuration::updateValue('RETAILCRM_API_TOKEN', $token); + Configuration::updateValue('RETAILCRM_API_VERSION', $version); Configuration::updateValue('RETAILCRM_API_DELIVERY', $delivery); Configuration::updateValue('RETAILCRM_API_STATUS', $status); Configuration::updateValue('RETAILCRM_API_PAYMENT', $payment); @@ -99,25 +109,26 @@ class RetailCRM extends Module Configuration::updateValue('RETAILCRM_API_PAYMENT_DEFAULT', $paymentDefault); $output .= $this->displayConfirmation($this->l('Settings updated')); + } - $this->apiUrl = $address; - $this->apiKey = $token; - $this->api = new RetailcrmProxy($this->apiUrl, $this->apiKey, _PS_ROOT_DIR_ . '/retailcrm.log'); - $this->reference = new RetailcrmReferences($this->api); + if ($version == 5 && $this->isRegisteredInHook('actionPaymentCCAdd') == 0) { + $this->registerHook('actionPaymentCCAdd'); + } elseif ($version == 4 && $this->isRegisteredInHook('actionPaymentCCAdd') == 1) { + $hook_id = Hook::getIdByName('actionPaymentCCAdd'); + $this->unregisterHook($hook_id); } } - if (!$this->validateCrmAddress($this->apiUrl)) { - $output .= $this->displayError($this->l('Invalid or empty crm address')); - } elseif (!$token || $token == '') { - $output .= $this->displayError($this->l('Invalid or empty crm api token')); - } else { - $output .= $this->displayConfirmation( - $this->l('Timezone settings must be identical to both of your crm and shop') . - " $address/admin/settings#t-main" - ); + if ($address && $token) { + $this->api = new RetailcrmProxy($address, $token, $this->log, $version); + $this->reference = new RetailcrmReferences($this->api); } - + + $output .= $this->displayConfirmation( + $this->l('Timezone settings must be identical to both of your crm and shop') . + " $address/admin/settings#t-main" + ); + $this->display(__FILE__, 'retailcrm.tpl'); return $output . $this->displayForm(); @@ -129,7 +140,16 @@ class RetailCRM extends Module $this->displayConfirmation($this->l('Settings updated')); $default_lang = $this->default_lang; - + $apiVersions = array( + array( + 'option_id' => '4', + 'name' => 'v4' + ), + array( + 'option_id' => '5', + 'name' => 'v5' + ) + ); /* * Network connection form */ @@ -138,6 +158,16 @@ class RetailCRM extends Module 'title' => $this->l('Network connection'), ), 'input' => array( + array( + 'type' => 'select', + 'name' => 'RETAILCRM_API_VERSION', + 'label' => $this->l('API version'), + 'options' => array( + 'query' => $apiVersions, + 'id' => 'option_id', + 'name' => 'name' + ) + ), array( 'type' => 'text', 'label' => $this->l('CRM address'), @@ -232,6 +262,7 @@ class RetailCRM extends Module $helper->fields_value['RETAILCRM_ADDRESS'] = Configuration::get('RETAILCRM_ADDRESS'); $helper->fields_value['RETAILCRM_API_TOKEN'] = Configuration::get('RETAILCRM_API_TOKEN'); + $helper->fields_value['RETAILCRM_API_VERSION'] = Configuration::get('RETAILCRM_API_VERSION'); $deliverySettings = Configuration::get('RETAILCRM_API_DELIVERY'); if (isset($deliverySettings) && $deliverySettings != '') { @@ -332,20 +363,26 @@ class RetailCRM extends Module } public function hookActionOrderEdited($params) - { + { + $apiVersion = Configuration::get('RETAILCRM_API_VERSION'); $order = array( 'externalId' => $params['order']->id, 'firstName' => $params['customer']->firstname, 'lastName' => $params['customer']->lastname, 'email' => $params['customer']->email, - 'discount' => $params['order']->total_discounts, 'createdAt' => $params['order']->date_add, 'delivery' => array('cost' => $params['order']->total_shipping) ); + if ($apiVersion != 5) { + $order['discount'] = $params['order']->total_discounts; + } else { + $order['discountManualAmount'] = $params['order']->total_discounts; + } + $orderdb = new Order($params['order']->id); foreach ($orderdb->getProducts() as $item) { - if (isset($item['product_attribute_id']) && $item['product_attribute_id'] > 0) { + if(isset($item['product_attribute_id']) && $item['product_attribute_id'] > 0) { $productId = $item['product_id'] . '#' . $item['product_attribute_id']; } else { $productId = $item['product_id']; @@ -364,132 +401,150 @@ class RetailCRM extends Module } public function hookActionOrderStatusPostUpdate($params) - { + { $delivery = json_decode(Configuration::get('RETAILCRM_API_DELIVERY'), true); $payment = json_decode(Configuration::get('RETAILCRM_API_PAYMENT'), true); $status = json_decode(Configuration::get('RETAILCRM_API_STATUS'), true); + $apiVersion = Configuration::get('RETAILCRM_API_VERSION'); if (isset($params['orderStatus'])) { + $customer = array( + 'externalId' => $params['customer']->id, + 'lastName' => $params['customer']->lastname, + 'firstName' => $params['customer']->firstname, + 'email' => $params['customer']->email, + 'createdAt' => $params['customer']->date_add + ); - $customer = array( - 'externalId' => $params['customer']->id, - 'lastName' => $params['customer']->lastname, - 'firstName' => $params['customer']->firstname, - 'email' => $params['customer']->email, - 'createdAt' => $params['customer']->date_add + $order = array( + 'externalId' => $params['order']->id, + 'firstName' => $params['customer']->firstname, + 'lastName' => $params['customer']->lastname, + 'email' => $params['customer']->email, + 'createdAt' => $params['order']->date_add, + 'delivery' => array('cost' => $params['order']->total_shipping) + ); + + if ($apiVersion != 5) { + $order['discount'] = $params['order']->total_discounts; + } else { + $order['discountManualAmount'] = $params['order']->total_discounts; + } + + $cart = new Cart($params['cart']->id); + $addressCollection = $cart->getAddressCollection(); + $address = array_shift($addressCollection); + + if ($address instanceof Address) { + $phone = empty($address->phone) + ? empty($address->phone_mobile) ? '' : $address->phone_mobile + : $address->phone; + + $postcode = $address->postcode; + $city = $address->city; + $addres_line = sprintf("%s %s", $address->address1, $address->address2); + } + + if (!empty($postcode)) { + $customer['address']['index'] = $postcode; + $order['delivery']['address']['index'] = $postcode; + } + + if (!empty($city)) { + $customer['address']['city'] = $city; + $order['delivery']['address']['city'] = $city; + } + + if (!empty($addres_line)) { + $customer['address']['text'] = $addres_line; + $order['delivery']['address']['text'] = $addres_line; + } + + if (!empty($phone)) { + $customer['phones'][] = array('number' => $phone); + $order['phone'] = $phone; + } + + foreach ($cart->getProducts() as $item) { + if(isset($item['id_product_attribute']) && $item['id_product_attribute'] > 0) { + $productId = $item['id_product'] . '#' . $item['id_product_attribute']; + } else { + $productId = $item['id_product']; + } + + if ($item['attributes']) { + $arProp = array(); + $count = 0; + $arAttr = explode(",", $item['attributes']); + foreach ($arAttr as $valAttr) { + $arItem = explode(":", $valAttr); + $arProp[$count]['name'] = trim($arItem[0]); + $arProp[$count]['value'] = trim($arItem[1]); + $count++; + + } + } + + $order['items'][] = array( + 'initialPrice' => !empty($item['rate']) + ? $item['price'] + ($item['price'] * $item['rate'] / 100) + : $item['price'], + 'quantity' => $item['quantity'], + 'offer' => array('externalId' => $productId), + 'productName' => $item['name'], + 'properties' => $arProp ); - $order = array( - 'externalId' => $params['order']->id, - 'firstName' => $params['customer']->firstname, - 'lastName' => $params['customer']->lastname, - 'email' => $params['customer']->email, - 'discount' => $params['order']->total_discounts, - 'createdAt' => $params['order']->date_add, - 'delivery' => array('cost' => $params['order']->total_shipping) - ); + unset($arAttr); + unset($count); + unset($arProp); + } - $cart = new Cart($params['cart']->id); - $addressCollection = $cart->getAddressCollection(); - $address = array_shift($addressCollection); + $deliveryCode = $params['order']->id_carrier; - if ($address instanceof Address) { - $phone = empty($address->phone) - ? empty($address->phone_mobile) ? '' : $address->phone_mobile - : $address->phone; + if (array_key_exists($deliveryCode, $delivery) && !empty($delivery[$deliveryCode])) { + $order['delivery']['code'] = $delivery[$deliveryCode]; + } - $postcode = $address->postcode; - $city = $address->city; - $addres_line = sprintf("%s %s", $address->address1, $address->address2); - } - - if (!empty($postcode)) { - $customer['address']['index'] = $postcode; - $order['delivery']['address']['index'] = $postcode; - } - - if (!empty($city)) { - $customer['address']['city'] = $city; - $order['delivery']['address']['city'] = $city; - } - - if (!empty($addres_line)) { - $customer['address']['text'] = $addres_line; - $order['delivery']['address']['text'] = $addres_line; - } - - if (!empty($phone)) { - $customer['phones'][] = array('number' => $phone); - $order['phone'] = $phone; - } - - foreach ($cart->getProducts() as $item) { - if (isset($item['id_product_attribute']) && $item['id_product_attribute'] > 0) { - $productId = $item['id_product'] . '#' . $item['id_product_attribute']; - } else { - $productId = $item['id_product']; - } - - if ($item['attributes']) { - $arProp = array(); - $count = 0; - $arAttr = explode(",", $item['attributes']); - foreach ($arAttr as $valAttr) { - $arItem = explode(":", $valAttr); - $arProp[$count]['name'] = trim($arItem[0]); - $arProp[$count]['value'] = trim($arItem[1]); - $count++; - - } - } - - $order['items'][] = array( - 'initialPrice' => !empty($item['rate']) - ? $item['price'] + ($item['price'] * $item['rate'] / 100) - : $item['price'], - 'quantity' => $item['quantity'], - 'offer' => array('externalId' => $productId), - 'productName' => $item['name'], - 'properties' => $arProp - ); - - unset($arAttr, $count, $arProp); - } - - $deliveryCode = $params['order']->id_carrier; - - if (array_key_exists($deliveryCode, $delivery) && !empty($delivery[$deliveryCode])) { - $order['delivery']['code'] = $delivery[$deliveryCode]; - } - - if (Module::getInstanceByName('advancedcheckout') === false) { + if (Module::getInstanceByName('advancedcheckout') === false) { $paymentCode = $params['order']->module; } else { $paymentCode = $params['order']->payment; } + if ($apiVersion != 5) { if (array_key_exists($paymentCode, $payment) && !empty($payment[$paymentCode])) { $order['paymentType'] = $payment[$paymentCode]; } + } else { + $payment = array( + 'externalId' => $params['order']->id .'#'. $params['order']->reference, + 'amount' => $params['order']->total_paid, + 'type' => $payment[$paymentCode] ? $payment[$paymentCode] : '' + ); + } - $statusCode = $params['orderStatus']->id; + if (isset($payment)) $order['payments'][] = $payment; - if (array_key_exists($statusCode, $status) && !empty($status[$statusCode])) { - $order['status'] = $status[$statusCode]; - } else { - $order['status'] = 'new'; - } + $statusCode = $params['orderStatus']->id; - $customerCheck = $this->api->customersGet($customer['externalId']); + if (array_key_exists($statusCode, $status) && !empty($status[$statusCode])) { + $order['status'] = $status[$statusCode]; + } else { + $order['status'] = 'new'; + } - if ($customerCheck === false) { - $this->api->customersCreate($customer); - } + $customerCheck = $this->api->customersGet($customer['externalId']); - $order['customer']['externalId'] = $customer['externalId']; - $this->api->ordersCreate($order); + if ($customerCheck === false) { + $this->api->customersCreate($customer); + } - } elseif (isset($params['newOrderStatus'])) { + $order['customer']['externalId'] = $customer['externalId']; + + $this->api->ordersCreate($order); + + } elseif (isset($params['newOrderStatus'])){ $statusCode = $params['newOrderStatus']->id; @@ -510,10 +565,84 @@ class RetailCRM extends Module } } + public function hookActionPaymentCCAdd($params) + { + $order_id = Order::getOrderByCartId($params['cart']->id); + $payments = $this->reference->getSystemPaymentModules(); + $paymentCRM = json_decode(Configuration::get('RETAILCRM_API_PAYMENT'), true); + + foreach ($payments as $valPay) { + if ($valPay['name'] == $params['paymentCC']->payment_method) { + $payCode = $valPay['code']; + } + } + + if (array_key_exists($payCode, $paymentCRM) && !empty($paymentCRM[$payCode])) { + $payment = $paymentCRM[$payCode]; + } + + $response = $this->api->ordersGet($order_id); + + if ($response->isSuccessful()) { + $orderCRM = $response['order']; + if ($orderCRM && $orderCRM['payments']) { + foreach ($orderCRM['payments'] as $orderPayment) { + if ($orderPayment['type'] == $payment) { + $updatePayment = $orderPayment; + $updatePayment['amount'] = $params['paymentCC']->amount; + $updatePayment['paidAt'] = $params['paymentCC']->date_add; + if ($params['paymentCC']->amount == $orderCRM['totalSumm']) { + $updatePayment['status'] = 'paid'; + } + } + } + } + } + + if (isset($updatePayment)) { + $this->api->ordersPaymentEdit($updatePayment); + } else { + $this->api->ordersPaymentCreate( + array( + 'externalId' => $params['paymentCC']->id, + 'amount' => $params['paymentCC']->amount, + 'paidAt' => $params['paymentCC']->date_add, + 'type' => $payment, + 'status' => 'paid', + 'order' => array( + 'externalId' => $order_id, + ), + ) + ); + } + return true; + } + private function validateCrmAddress($address) { - if (preg_match("/https:\/\/(.*).retailcrm.ru/", $address) === 1) + if(preg_match("/https:\/\/(.*).retailcrm.ru/", $address) === 1) return true; return false; } + + private function validateApiVersion($settings) { + $api = new RetailcrmProxy($settings['address'], $settings['token'], _PS_ROOT_DIR_ . '/retailcrm.log', $settings['version']); + $response = $api->statisticUpdate(); + + if ($response->isSuccessful()) return true; + + return false; + } + + private function validateForm($settings, $output) { + if (!$this->validateCrmAddress($settings['address']) || !Validate::isGenericName($settings['address'])) { + $output .= $this->displayError($this->l('Invalid or empty crm address')); + } elseif (!$settings['token'] || $settings['token'] == '') { + $output .= $this->displayError($this->l('Invalid or empty crm api token')); + } elseif (!$this->validateApiVersion($settings)) { + $output .= $this->displayError($this->l('The selected version of the API is unavailable')); + } + + return $output; + } } diff --git a/retailcrm/translations/ru.php b/retailcrm/translations/ru.php index cc9019e..edc5325 100644 --- a/retailcrm/translations/ru.php +++ b/retailcrm/translations/ru.php @@ -2,6 +2,7 @@ global $_MODULE; $_MODULE = array(); +$_MODULE['<{retailcrm}prestashop>retailcrm_7d1d9327371097419bdf83ffa671d2f2'] = 'Версия API'; $_MODULE['<{retailcrm}prestashop>retailcrm_463dc31aa1a0b6e871b1a9fed8e9860a'] = 'RetailCRM'; $_MODULE['<{retailcrm}prestashop>retailcrm_30de6237576b9a24f6fc599c22a35a4b'] = 'Модуль интеграции с RetailCRM'; $_MODULE['<{retailcrm}prestashop>retailcrm_876f23178c29dc2552c0b48bf23cd9bd'] = 'Вы уверены, что хотите удалить модуль?'; @@ -49,4 +50,4 @@ $_MODULE['<{retailcrm}prestashop>retailcrm_69aede266809f89b89fe70681f6a129f'] = $_MODULE['<{retailcrm}prestashop>retailcrm_57d056ed0984166336b7879c2af3657f'] = 'Город'; $_MODULE['<{retailcrm}prestashop>retailcrm_bcc254b55c4a1babdf1dcb82c207506b'] = 'Телефон'; $_MODULE['<{retailcrm}prestashop>retailcrm_f0e1fc6f97d36cb80f29196e2662ffde'] = 'Мобильный телефон'; -$_MODULE['<{retailcrm}prestashop>retailcrm_7a1920d61156abc05a60135aefe8bc67'] = 'По умолчанию'; +$_MODULE['<{retailcrm}prestashop>retailcrm_7a1920d61156abc05a60135aefe8bc67'] = 'По умолчанию'; \ No newline at end of file