diff --git a/LICENSE b/LICENSE
index 6e851f2..7d0bf51 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2017 retailCRM
+Copyright (c) 2017 RetailDriver LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/retailcrm/include-custom/index.php b/retailcrm/include-custom/index.php
new file mode 100644
index 0000000..e71af0e
--- /dev/null
+++ b/retailcrm/include-custom/index.php
@@ -0,0 +1 @@
+
+ * @license https://opensource.org/licenses/MIT MIT License
+ * @link http://retailcrm.ru/docs/Developers/ApiVersion4
+ */
+
+ if ( ! class_exists( 'WC_Retailcrm_Request' ) ) {
+ include_once( __DIR__ . '/class-wc-retailcrm-request.php' );
+ }
+
+ if ( ! class_exists( 'WC_Retailcrm_Response' ) ) {
+ include_once( __DIR__ . '/class-wc-retailcrm-response.php' );
+ }
+
+ class WC_Retailcrm_Client
+ {
+
+ const VERSION = 'v4';
+
+ protected $client;
+
+ /**
+ * Site code
+ */
+ protected $siteCode;
+
+ /**
+ * WC_Retailcrm_Request creating
+ *
+ * @param string $url api url
+ * @param string $apiKey api key
+ * @param string $site site code
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function __construct($url, $apiKey, $site = null)
+ {
+ if ('/' !== $url[strlen($url) - 1]) {
+ $url .= '/';
+ }
+
+ $url = $url . 'api/' . self::VERSION;
+
+ $this->client = new WC_Retailcrm_Request($url, array('apiKey' => $apiKey));
+ $this->siteCode = $site;
+ }
+
+ /**
+ * Returns users list
+ *
+ * @param array $filter
+ * @param null $page
+ * @param null $limit
+ *
+ * @throws WC_Retailcrm_Exception_Json
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws \InvalidArgumentException
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Get user groups
+ *
+ * @param null $page
+ * @param null $limit
+ *
+ * @throws WC_Retailcrm_Exception_Json
+ * @throws WC_Retailcrm_Exception_Curl
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function usersGroups($page = null, $limit = null)
+ {
+ $parameters = array();
+
+ if (null !== $page) {
+ $parameters['page'] = (int) $page;
+ }
+ if (null !== $limit) {
+ $parameters['limit'] = (int) $limit;
+ }
+
+ return $this->client->makeRequest(
+ '/user-groups',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Returns user data
+ *
+ * @param integer $id user ID
+ *
+ * @throws WC_Retailcrm_Exception_Json
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws \InvalidArgumentException
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function usersGet($id)
+ {
+ return $this->client->makeRequest("/users/$id", WC_Retailcrm_Request::METHOD_GET);
+ }
+
+ /**
+ * Returns filtered orders list
+ *
+ * @param array $filter (default: array())
+ * @param int $page (default: null)
+ * @param int $limit (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Create a order
+ *
+ * @param array $order order data
+ * @param string $site (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::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 WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::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 WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Upload array of the orders
+ *
+ * @param array $orders array of orders
+ * @param string $site (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::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 WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function ordersGet($id, $by = 'externalId', $site = null)
+ {
+ $this->checkIdParameter($by);
+
+ return $this->client->makeRequest(
+ "/orders/$id",
+ WC_Retailcrm_Request::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 WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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]),
+ WC_Retailcrm_Request::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 WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Returns filtered customers list
+ *
+ * @param array $filter (default: array())
+ * @param int $page (default: null)
+ * @param int $limit (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Create a customer
+ *
+ * @param array $customer customer data
+ * @param string $site (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::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 WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::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 WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::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 WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function customersGet($id, $by = 'externalId', $site = null)
+ {
+ $this->checkIdParameter($by);
+
+ return $this->client->makeRequest(
+ "/customers/$id",
+ WC_Retailcrm_Request::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 WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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]),
+ WC_Retailcrm_Request::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 WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Get orders assembly list
+ *
+ * @param array $filter (default: array())
+ * @param int $page (default: null)
+ * @param int $limit (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Create orders assembly
+ *
+ * @param array $pack pack data
+ * @param string $site (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::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 WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Get orders assembly by id
+ *
+ * @param string $id pack identificator
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function ordersPacksGet($id)
+ {
+ if (empty($id)) {
+ throw new \InvalidArgumentException('Parameter `id` must be set');
+ }
+
+ return $this->client->makeRequest(
+ "/orders/packs/$id",
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Delete orders assembly by id
+ *
+ * @param string $id pack identificator
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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),
+ WC_Retailcrm_Request::METHOD_POST
+ );
+ }
+
+ /**
+ * Edit orders assembly
+ *
+ * @param array $pack pack data
+ * @param string $site (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ $this->fillSite($site, array('pack' => json_encode($pack)))
+ );
+ }
+
+ /**
+ * Get purchace prices & stock balance
+ *
+ * @param array $filter (default: array())
+ * @param int $page (default: null)
+ * @param int $limit (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Get store settings
+ *
+ * @param string $code get settings code
+ *
+ * @return WC_Retailcrm_Response
+ * @throws WC_Retailcrm_Exception_Json
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws \InvalidArgumentException
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function storeSettingsGet($code)
+ {
+ if (empty($code)) {
+ throw new \InvalidArgumentException('Parameter `code` must be set');
+ }
+
+ return $this->client->makeRequest(
+ "/store/setting/$code",
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit store configuration
+ *
+ * @param array $configuration
+ *
+ * @throws WC_Retailcrm_Exception_Json
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws \InvalidArgumentException
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('configuration' => json_encode($configuration))
+ );
+ }
+
+ /**
+ * Upload store inventories
+ *
+ * @param array $offers offers data
+ * @param string $site (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_POST,
+ $this->fillSite($site, array('offers' => json_encode($offers)))
+ );
+ }
+
+ /**
+ * Upload store prices
+ *
+ * @param array $prices prices data
+ * @param string $site default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function storePricesUpload(array $prices, $site = null)
+ {
+ if (!count($prices)) {
+ throw new \InvalidArgumentException(
+ 'Parameter `prices` must contains array of the prices'
+ );
+ }
+
+ return $this->client->makeRequest(
+ '/store/prices/upload',
+ WC_Retailcrm_Request::METHOD_POST,
+ $this->fillSite($site, array('prices' => json_encode($prices)))
+ );
+ }
+
+ /**
+ * Get products
+ *
+ * @param array $filter (default: array())
+ * @param int $page (default: null)
+ * @param int $limit (default: null)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Get delivery settings
+ *
+ * @param string $code
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function deliverySettingsGet($code)
+ {
+ if (empty($code)) {
+ throw new \InvalidArgumentException('Parameter `code` must be set');
+ }
+
+ return $this->client->makeRequest(
+ "/delivery/generic/setting/$code",
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit delivery configuration
+ *
+ * @param array $configuration
+ *
+ * @throws WC_Retailcrm_Exception_Json
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws \InvalidArgumentException
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('configuration' => json_encode($configuration))
+ );
+ }
+
+ /**
+ * Delivery tracking update
+ *
+ * @param string $code
+ * @param array $statusUpdate
+ *
+ * @throws WC_Retailcrm_Exception_Json
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws \InvalidArgumentException
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('statusUpdate' => json_encode($statusUpdate))
+ );
+ }
+
+ /**
+ * Returns available county list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function countriesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/countries',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Returns deliveryServices list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function deliveryServicesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/delivery-services',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit deliveryService
+ *
+ * @param array $data delivery service data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('deliveryService' => json_encode($data))
+ );
+ }
+
+ /**
+ * Returns deliveryTypes list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function deliveryTypesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/delivery-types',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit deliveryType
+ *
+ * @param array $data delivery type data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('deliveryType' => json_encode($data))
+ );
+ }
+
+ /**
+ * Returns orderMethods list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function orderMethodsList()
+ {
+ return $this->client->makeRequest(
+ '/reference/order-methods',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit orderMethod
+ *
+ * @param array $data order method data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('orderMethod' => json_encode($data))
+ );
+ }
+
+ /**
+ * Returns orderTypes list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function orderTypesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/order-types',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit orderType
+ *
+ * @param array $data order type data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('orderType' => json_encode($data))
+ );
+ }
+
+ /**
+ * Returns paymentStatuses list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function paymentStatusesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/payment-statuses',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit paymentStatus
+ *
+ * @param array $data payment status data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('paymentStatus' => json_encode($data))
+ );
+ }
+
+ /**
+ * Returns paymentTypes list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function paymentTypesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/payment-types',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit paymentType
+ *
+ * @param array $data payment type data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('paymentType' => json_encode($data))
+ );
+ }
+
+ /**
+ * Returns productStatuses list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function productStatusesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/product-statuses',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit productStatus
+ *
+ * @param array $data product status data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('productStatus' => json_encode($data))
+ );
+ }
+
+ /**
+ * Returns sites list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function sitesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/sites',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit site
+ *
+ * @param array $data site data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('site' => json_encode($data))
+ );
+ }
+
+ /**
+ * Returns statusGroups list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function statusGroupsList()
+ {
+ return $this->client->makeRequest(
+ '/reference/status-groups',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Returns statuses list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function statusesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/statuses',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit order status
+ *
+ * @param array $data status data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('status' => json_encode($data))
+ );
+ }
+
+ /**
+ * Returns stores list
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function storesList()
+ {
+ return $this->client->makeRequest(
+ '/reference/stores',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit store
+ *
+ * @param array $data site data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('store' => json_encode($data))
+ );
+ }
+
+ /**
+ * Get prices types
+ *
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function pricesTypes()
+ {
+ return $this->client->makeRequest(
+ '/reference/price-types',
+ WC_Retailcrm_Request::METHOD_GET
+ );
+ }
+
+ /**
+ * Edit price type
+ *
+ * @param array $data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function pricesEdit(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/price-types/%s/edit', $data['code']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('priceType' => json_encode($data))
+ );
+ }
+
+ /**
+ * Get telephony settings
+ *
+ * @param string $code
+ *
+ * @throws WC_Retailcrm_Exception_Json
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws \InvalidArgumentException
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function telephonySettingsGet($code)
+ {
+ if (empty($code)) {
+ throw new \InvalidArgumentException('Parameter `code` must be set');
+ }
+
+ return $this->client->makeRequest(
+ "/telephony/setting/$code",
+ WC_Retailcrm_Request::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 WC_Retailcrm_Response
+ */
+ 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",
+ WC_Retailcrm_Request::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 WC_Retailcrm_Response
+ * @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',
+ WC_Retailcrm_Request::METHOD_POST,
+ array('event' => json_encode($parameters))
+ );
+ }
+
+ /**
+ * Upload calls
+ *
+ * @param array $calls calls data
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_POST,
+ array('calls' => json_encode($calls))
+ );
+ }
+
+ /**
+ * Get call manager
+ *
+ * @param string $phone phone number
+ * @param bool $details detailed information
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ 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',
+ WC_Retailcrm_Request::METHOD_GET,
+ $parameters
+ );
+ }
+
+ /**
+ * Edit marketplace configuration
+ *
+ * @param array $configuration
+ *
+ * @throws WC_Retailcrm_Exception_Json
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws \InvalidArgumentException
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function marketplaceSettingsEdit(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('/marketplace/external/setting/%s/edit', $configuration['code']),
+ WC_Retailcrm_Request::METHOD_POST,
+ array('configuration' => json_encode($configuration))
+ );
+ }
+
+ /**
+ * Update CRM basic statistic
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ * @throws WC_Retailcrm_Exception_Json
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function statisticUpdate()
+ {
+ return $this->client->makeRequest(
+ '/statistic/update',
+ WC_Retailcrm_Request::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/include/api/class-wc-retailcrm-exception-curl.php b/retailcrm/include/api/class-wc-retailcrm-exception-curl.php
new file mode 100644
index 0000000..f22c34e
--- /dev/null
+++ b/retailcrm/include/api/class-wc-retailcrm-exception-curl.php
@@ -0,0 +1,16 @@
+
+ * @license https://opensource.org/licenses/MIT MIT License
+ * @link http://retailcrm.ru/docs/Developers/ApiVersion4
+ */
+ class WC_Retailcrm_Exception_Curl extends \RuntimeException
+ {
+ }
diff --git a/retailcrm/include/api/class-wc-retailcrm-exception-json.php b/retailcrm/include/api/class-wc-retailcrm-exception-json.php
new file mode 100644
index 0000000..acb8cfa
--- /dev/null
+++ b/retailcrm/include/api/class-wc-retailcrm-exception-json.php
@@ -0,0 +1,17 @@
+
+ * @license https://opensource.org/licenses/MIT MIT License
+ * @link http://retailcrm.ru/docs/Developers/ApiVersion4
+ */
+
+ class WC_Retailcrm_Exception_Json extends \DomainException
+ {
+ }
diff --git a/retailcrm/include/api/class-wc-retailcrm-proxy.php b/retailcrm/include/api/class-wc-retailcrm-proxy.php
new file mode 100644
index 0000000..ed8d763
--- /dev/null
+++ b/retailcrm/include/api/class-wc-retailcrm-proxy.php
@@ -0,0 +1,63 @@
+logger = new WC_Logger();
+
+ if ( ! class_exists( 'WC_Retailcrm_Client' ) ) {
+ include_once( __DIR__ . '/class-wc-retailcrm-client.php' );
+ }
+
+ if ($api_url && $api_key) {
+ $this->retailcrm = new WC_Retailcrm_Client($api_url, $api_key);
+ }
+ }
+
+ public function __call($method, $arguments)
+ {
+ try {
+ $response = call_user_func_array(array($this->retailcrm, $method), $arguments);
+
+ if ($response->isSuccessful()) {
+ $result = ' Ok';
+ } else {
+ $result = sprintf(
+ $method ." : Error: [HTTP-code %s] %s",
+ $response->getStatusCode(),
+ $response->getErrorMsg()
+ );
+
+ if (isset($response['errors'])) {
+ foreach ($response['errors'] as $error) {
+ $result .= " $error";
+ }
+ }
+ }
+
+ $this->logger->add('retailcrm', sprintf("[%s] %s", $method, $result));
+ } catch (WC_Retailcrm_Exception_Curl $exception) {
+ $this->logger->add('retailcrm', sprintf("[%s] %s - %s", $method, $exception->getMessage(), $result));
+ } catch (WC_Retailcrm_Exception_Json $exception) {
+ $this->logger->add('retailcrm', sprintf("[%s] %s - %s", $method, $exception->getMessage(), $result));
+ } catch (InvalidArgumentException $exception) {
+ $this->logger->add('retailcrm', sprintf("[%s] %s - %s", $method, $exception->getMessage(), $result));
+ }
+
+ return $response;
+ }
+ }
+endif;
\ No newline at end of file
diff --git a/retailcrm/include/api/class-wc-retailcrm-request.php b/retailcrm/include/api/class-wc-retailcrm-request.php
new file mode 100644
index 0000000..00cf9b3
--- /dev/null
+++ b/retailcrm/include/api/class-wc-retailcrm-request.php
@@ -0,0 +1,118 @@
+
+ * @license https://opensource.org/licenses/MIT MIT License
+ * @link http://retailcrm.ru/docs/Developers/ApiVersion4
+ */
+
+ if ( ! class_exists( 'WC_Retailcrm_Exception_Curl' ) ) {
+ include_once( __DIR__ . '/class-wc-retailcrm-exception-curl.php' );
+ }
+
+ if ( ! class_exists( 'WC_Retailcrm_Response' ) ) {
+ include_once( __DIR__ . '/class-wc-retailcrm-response.php' );
+ }
+
+ class WC_Retailcrm_Request
+ {
+ const METHOD_GET = 'GET';
+ const METHOD_POST = 'POST';
+
+ protected $url;
+ protected $defaultParameters;
+
+ /**
+ * Client constructor.
+ *
+ * @param string $url api url
+ * @param array $defaultParameters array of parameters
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function __construct($url, array $defaultParameters = array())
+ {
+ if (false === stripos($url, 'https://')) {
+ throw new \InvalidArgumentException(
+ 'API schema requires HTTPS protocol'
+ );
+ }
+
+ $this->url = $url;
+ $this->defaultParameters = $defaultParameters;
+ }
+
+ /**
+ * Make HTTP request
+ *
+ * @param string $path request url
+ * @param string $method (default: 'GET')
+ * @param array $parameters (default: array())
+ *
+ * @SuppressWarnings(PHPMD.ExcessiveParameterList)
+ *
+ * @throws \InvalidArgumentException
+ * @throws WC_Retailcrm_Exception_Curl
+ *
+ * @return WC_Retailcrm_Response
+ */
+ public function makeRequest(
+ $path,
+ $method,
+ array $parameters = array()
+ ) {
+ $allowedMethods = array(self::METHOD_GET, self::METHOD_POST);
+
+ if (!in_array($method, $allowedMethods, false)) {
+ throw new \InvalidArgumentException(
+ sprintf(
+ 'Method "%s" is not valid. Allowed methods are %s',
+ $method,
+ implode(', ', $allowedMethods)
+ )
+ );
+ }
+
+ $parameters = array_merge($this->defaultParameters, $parameters);
+
+ $url = $this->url . $path;
+
+ if (self::METHOD_GET === $method && count($parameters)) {
+ $url .= '?' . http_build_query($parameters, '', '&');
+ }
+
+ $curlHandler = curl_init();
+ curl_setopt($curlHandler, CURLOPT_URL, $url);
+ curl_setopt($curlHandler, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($curlHandler, CURLOPT_FOLLOWLOCATION, 1);
+ curl_setopt($curlHandler, CURLOPT_FAILONERROR, false);
+ curl_setopt($curlHandler, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($curlHandler, CURLOPT_SSL_VERIFYHOST, false);
+ curl_setopt($curlHandler, CURLOPT_TIMEOUT, 30);
+ curl_setopt($curlHandler, CURLOPT_CONNECTTIMEOUT, 30);
+
+ if (self::METHOD_POST === $method) {
+ curl_setopt($curlHandler, CURLOPT_POST, true);
+ curl_setopt($curlHandler, CURLOPT_POSTFIELDS, $parameters);
+ }
+
+ $responseBody = curl_exec($curlHandler);
+ $statusCode = curl_getinfo($curlHandler, CURLINFO_HTTP_CODE);
+ $errno = curl_errno($curlHandler);
+ $error = curl_error($curlHandler);
+
+ curl_close($curlHandler);
+
+ if ($errno) {
+ throw new WC_Retailcrm_Exception_Curl($error, $errno);
+ }
+
+ return new WC_Retailcrm_Response($statusCode, $responseBody);
+ }
+ }
diff --git a/retailcrm/include/api/class-wc-retailcrm-response.php b/retailcrm/include/api/class-wc-retailcrm-response.php
new file mode 100644
index 0000000..c3d753c
--- /dev/null
+++ b/retailcrm/include/api/class-wc-retailcrm-response.php
@@ -0,0 +1,170 @@
+
+ * @license https://opensource.org/licenses/MIT MIT License
+ * @link http://retailcrm.ru/docs/Developers/ApiVersion4
+ */
+
+ if ( ! class_exists( 'WC_Retailcrm_Exception_Json' ) ) {
+ include_once( __DIR__ . '/class-wc-retailcrm-exception-json.php' );
+ }
+
+
+ class WC_Retailcrm_Response implements \ArrayAccess
+ {
+ // HTTP response status code
+ protected $statusCode;
+
+ // response assoc array
+ protected $response;
+
+ /**
+ * ApiResponse constructor.
+ *
+ * @param int $statusCode HTTP status code
+ * @param mixed $responseBody HTTP body
+ *
+ * @throws WC_Retailcrm_Exception_Json
+ */
+ public function __construct($statusCode, $responseBody = null)
+ {
+ $this->statusCode = (int) $statusCode;
+
+ if (!empty($responseBody)) {
+ $response = json_decode($responseBody, true);
+
+ if (!$response && JSON_ERROR_NONE !== ($error = json_last_error())) {
+ throw new WC_Retailcrm_Exception_Json(
+ "Invalid JSON in the API response body. Error code #$error",
+ $error
+ );
+ }
+
+ $this->response = $response;
+ }
+ }
+
+ /**
+ * Return HTTP response status code
+ *
+ * @return int
+ */
+ public function getStatusCode()
+ {
+ return $this->statusCode;
+ }
+
+ /**
+ * HTTP request was successful
+ *
+ * @return bool
+ */
+ public function isSuccessful()
+ {
+ return $this->statusCode < 400;
+ }
+
+ /**
+ * Allow to access for the property throw class method
+ *
+ * @param string $name method name
+ * @param mixed $arguments method parameters
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return mixed
+ */
+ public function __call($name, $arguments)
+ {
+ // convert getSomeProperty to someProperty
+ $propertyName = strtolower(substr($name, 3, 1)) . substr($name, 4);
+
+ if (!isset($this->response[$propertyName])) {
+ throw new \InvalidArgumentException("Method \"$name\" not found");
+ }
+
+ return $this->response[$propertyName];
+ }
+
+ /**
+ * Allow to access for the property throw object property
+ *
+ * @param string $name property name
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return mixed
+ */
+ public function __get($name)
+ {
+ if (!isset($this->response[$name])) {
+ throw new \InvalidArgumentException("Property \"$name\" not found");
+ }
+
+ return $this->response[$name];
+ }
+
+ /**
+ * Offset set
+ *
+ * @param mixed $offset offset
+ * @param mixed $value value
+ *
+ * @throws \BadMethodCallException
+ * @return void
+ */
+ public function offsetSet($offset, $value)
+ {
+ throw new \BadMethodCallException('This activity not allowed');
+ }
+
+ /**
+ * Offset unset
+ *
+ * @param mixed $offset offset
+ *
+ * @throws \BadMethodCallException
+ * @return void
+ */
+ public function offsetUnset($offset)
+ {
+ throw new \BadMethodCallException('This call not allowed');
+ }
+
+ /**
+ * Check offset
+ *
+ * @param mixed $offset offset
+ *
+ * @return bool
+ */
+ public function offsetExists($offset)
+ {
+ return isset($this->response[$offset]);
+ }
+
+ /**
+ * Get offset
+ *
+ * @param mixed $offset offset
+ *
+ * @throws \InvalidArgumentException
+ *
+ * @return mixed
+ */
+ public function offsetGet($offset)
+ {
+ if (!isset($this->response[$offset])) {
+ throw new \InvalidArgumentException("Property \"$offset\" not found");
+ }
+
+ return $this->response[$offset];
+ }
+ }
diff --git a/retailcrm/include/api/index.php b/retailcrm/include/api/index.php
new file mode 100644
index 0000000..e71af0e
--- /dev/null
+++ b/retailcrm/include/api/index.php
@@ -0,0 +1 @@
+id = 'integration-retailcrm';
+ $this->method_title = __( 'Retailcrm', 'woocommerce-integration-retailcrm' );
+ $this->method_description = __( 'Интеграция с системой управления Retailcrm.', 'woocommerce-integration-retailcrm' );
+
+ // Load the settings.
+
+ $this->init_form_fields();
+ $this->init_settings();
+
+ // Actions.
+ add_action( 'woocommerce_update_options_integration_' . $this->id, array( $this, 'process_admin_options' ) );
+ }
+
+ /**
+ * Initialize integration settings form fields.
+ */
+ public function init_form_fields() {
+
+ $this->form_fields = array(
+ array( 'title' => __( 'Общие настройки', 'woocommerce' ), 'type' => 'title', 'desc' => '', 'id' => 'general_options' ),
+
+ 'api_url' => array(
+ 'title' => __( 'API URL', 'woocommerce-integration-retailcrm' ),
+ 'type' => 'text',
+ 'description' => __( 'Введите адрес вашей CRM (https://yourdomain.retailcrm.ru).', 'woocommerce-integration-retailcrm' ),
+ 'desc_tip' => true,
+ 'default' => ''
+ ),
+ 'api_key' => array(
+ 'title' => __( 'API Ключ', 'woocommerce-integration-retailcrm' ),
+ 'type' => 'text',
+ 'description' => __( 'Введите ключ API. Вы можете найти его в интерфейсе администратора Retailcrm.', 'woocommerce-integration-retailcrm' ),
+ 'desc_tip' => true,
+ 'default' => ''
+ )
+ );
+
+ if ($this->get_option( 'api_url' ) != '' && $this->get_option( 'api_key' ) != '') {
+
+ if ( ! class_exists( 'WC_Retailcrm_Client' ) ) {
+ include_once( __DIR__ . '/api/class-wc-retailcrm-client.php' );
+ }
+
+ $retailcrm = new WC_Retailcrm_Client(
+ $this->get_option( 'api_url' ),
+ $this->get_option( 'api_key' )
+ );
+
+ /**
+ * Shipping options
+ */
+
+ $shipping_option_list = array();
+ $retailcrm_shipping_list = $retailcrm->deliveryTypesList();
+
+ foreach ($retailcrm_shipping_list['deliveryTypes'] as $retailcrm_shipping_type) {
+ $shipping_option_list[$retailcrm_shipping_type['code']] = $retailcrm_shipping_type['name'];
+ }
+
+ $wc_shipping = new WC_Shipping();
+ $wc_shipping_list = $wc_shipping->get_shipping_methods();
+
+ $this->form_fields[] = array(
+ 'title' => __( 'Способы доставки', 'woocommerce' ),
+ 'type' => 'title',
+ 'description' => '',
+ 'id' => 'shipping_options'
+ );
+
+ foreach ( $wc_shipping_list as $shipping ) {
+ if ( isset( $shipping->enabled ) && $shipping->enabled == 'yes' ) {
+ $key = $shipping->id;
+ $name = $key;
+ $this->form_fields[$name] = array(
+ 'title' => __( $shipping->method_title, 'textdomain' ),
+ 'description' => __( $shipping->method_description, 'textdomain' ),
+ 'css' => 'min-width:350px;',
+ 'class' => 'select',
+ 'type' => 'select',
+ 'options' => $shipping_option_list,
+ 'desc_tip' => true,
+ );
+ }
+ }
+
+ /**
+ * Payment options
+ */
+
+ $payment_option_list = array();
+ $retailcrm_payment_list = $retailcrm->paymentTypesList();
+
+ foreach ($retailcrm_payment_list['paymentTypes'] as $retailcrm_payment_type) {
+ $payment_option_list[$retailcrm_payment_type['code']] = $retailcrm_payment_type['name'];
+ }
+
+ $wc_payment = new WC_Payment_Gateways();
+ $wc_payment_list = $wc_payment->get_available_payment_gateways();
+
+ $this->form_fields[] = array(
+ 'title' => __( 'Способы оплаты', 'woocommerce' ),
+ 'type' => 'title',
+ 'description' => '',
+ 'id' => 'payment_options'
+ );
+
+ foreach ( $wc_payment_list as $payment ) {
+ if ( isset( $payment->enabled ) && $payment->enabled == 'yes' ) {
+ $key = $payment->id;
+ $name = $key;
+ $this->form_fields[$name] = array(
+ 'title' => __( $payment->method_title, 'textdomain' ),
+ 'description' => __( $payment->method_description, 'textdomain' ),
+ 'css' => 'min-width:350px;',
+ 'class' => 'select',
+ 'type' => 'select',
+ 'options' => $payment_option_list,
+ 'desc_tip' => true,
+ );
+ }
+ }
+
+ /**
+ * Statuses options
+ */
+ $statuses_option_list = array();
+ $retailcrm_statuses_list = $retailcrm->statusesList();
+
+ foreach ($retailcrm_statuses_list['statuses'] as $retailcrm_status) {
+ $statuses_option_list[$retailcrm_status['code']] = $retailcrm_status['name'];
+ }
+
+ $wc_statuses = wc_get_order_statuses();
+
+ $this->form_fields[] = array(
+ 'title' => __( 'Статусы', 'woocommerce' ),
+ 'type' => 'title',
+ 'description' => '',
+ 'id' => 'statuses_options'
+ );
+
+ foreach ( $wc_statuses as $idx => $name ) {
+ $uid = str_replace('wc-', '', $idx);
+ $this->form_fields[$uid] = array(
+ 'title' => __( $name, 'textdomain' ),
+ 'css' => 'min-width:350px;',
+ 'class' => 'select',
+ 'type' => 'select',
+ 'options' => $statuses_option_list,
+ 'desc_tip' => true,
+ );
+ }
+
+ $this->form_fields[] = array(
+ 'title' => __( 'Настройки остатков', 'woocommerce' ),
+ 'type' => 'title',
+ 'description' => '',
+ 'id' => 'invent_options'
+ );
+
+ $this->form_fields['sync'] = array(
+ 'label' => __( 'Выгружать остатки из CRM', 'textdomain' ),
+ 'title' => 'Остатки',
+ 'class' => 'checkbox',
+ 'type' => 'checkbox',
+ 'description' => 'Отметьте данный пункт, если хотите выгружать остатки товаров из CRM в магазин.'
+ );
+
+ $this->form_fields[] = array(
+ 'title' => __( 'Настройки выгрузки', 'woocommerce' ),
+ 'type' => 'title',
+ 'description' => '',
+ 'id' => 'upload_options'
+ );
+
+ $this->form_fields['uploadToCrm'] = array(
+ 'label' => __( 'Выгрузить все заказы и клиентов', 'textdomain' ),
+ 'title' => 'Выгрузка заказов и клиентов',
+ 'class' => 'checkbox',
+ 'type' => 'checkbox',
+ 'description' => 'Поставьте галочку, и нажмите сохранить, чтобы выгрузить все существующие заказы и клиентов.'
+ );
+ }
+ }
+}
+
+endif;
diff --git a/retailcrm/include/class-wc-retailcrm-customers.php b/retailcrm/include/class-wc-retailcrm-customers.php
new file mode 100644
index 0000000..ca21839
--- /dev/null
+++ b/retailcrm/include/class-wc-retailcrm-customers.php
@@ -0,0 +1,121 @@
+retailcrm_settings = get_option( 'woocommerce_integration-retailcrm_settings' );
+
+ if ( ! class_exists( 'WC_Retailcrm_Proxy' ) ) {
+ include_once( __DIR__ . '/api/class-wc-retailcrm-proxy.php' );
+ }
+
+ $this->retailcrm = new WC_Retailcrm_Proxy(
+ $this->retailcrm_settings['api_url'],
+ $this->retailcrm_settings['api_key']
+ );
+ }
+
+ public function customersUpload()
+ {
+ $users = get_users();
+ $data_customers = array();
+
+ foreach ($users as $user) {
+ if ($user->roles[0] != 'customer') continue;
+
+ $customer = new WC_Customer($user->ID);
+
+ $data_customer = array(
+ 'createdAt' => $user->data->user_registered,
+ 'externalId' => $user->ID,
+ 'firstName' => !empty($customer->get_first_name()) ? $customer->get_first_name() : $customer->get_username(),
+ 'lastName' => $customer->get_last_name(),
+ 'email' => $user->data->user_email,
+ 'phones' => array(
+ array(
+ 'number' => $customer->get_billing_phone()
+ )
+ ),
+ 'address' => array(
+ 'index' => $customer->get_billing_postcode(),
+ 'countryIso' => $customer->get_billing_country(),
+ 'region' => $customer->get_billing_state(),
+ 'city' => $customer->get_billing_city(),
+ 'text' => $customer->get_billing_address_1() . ',' . $customer->get_billing_address_2()
+ )
+ );
+
+ $data_customers[] = $data_customer;
+ }
+
+ $data = array_chunk($data_customers, 50);
+
+ foreach ($data as $array_customers) {
+ $this->retailcrm->customersUpload($array_customers);
+ }
+ }
+
+ public function createCustomer($customer_id)
+ {
+ $customer = new WC_Customer($customer_id);
+
+ if ($customer->get_role() == 'customer'){
+
+ $data_customer = $this->processCustomer($customer);
+
+ $this->retailcrm->customersCreate($data_customer);
+ }
+ }
+
+ public function updateCustomer($customer_id)
+ {
+ $customer = new WC_Customer($customer_id);
+
+ if ($customer->get_role() == 'customer'){
+
+ $data_customer = $this->processCustomer($customer);
+
+ $this->retailcrm->customersEdit($data_customer);
+ }
+ }
+
+ protected function processCustomer($customer)
+ {
+ $createdAt = $customer->get_date_created();
+ $data_customer = array(
+ 'createdAt' => $createdAt->date('Y-m-d H:i:s '),
+ 'externalId' => $customer_id,
+ 'firstName' => !empty($customer->get_first_name()) ? $customer->get_first_name() : $customer->get_username(),
+ 'lastName' => $customer->get_last_name(),
+ 'email' => $customer->get_email(),
+ 'phones' => array(
+ array(
+ 'number' => $customer->get_billing_phone()
+ )
+ ),
+ 'address' => array(
+ 'index' => $customer->get_billing_postcode(),
+ 'countryIso' => $customer->get_billing_country(),
+ 'region' => $customer->get_billing_state(),
+ 'city' => $customer->get_billing_city(),
+ 'text' => $customer->get_billing_address_1() . ',' . $customer->get_billing_address_2()
+ )
+ );
+
+ return $data_customer;
+ }
+ }
+endif;
diff --git a/retailcrm/include/class-wc-retailcrm-history.php b/retailcrm/include/class-wc-retailcrm-history.php
new file mode 100644
index 0000000..558c4f2
--- /dev/null
+++ b/retailcrm/include/class-wc-retailcrm-history.php
@@ -0,0 +1,407 @@
+retailcrm_settings = get_option( 'woocommerce_integration-retailcrm_settings' );
+
+ if ( ! class_exists( 'WC_Retailcrm_Proxy' ) ) {
+ include_once( __DIR__ . '/api/class-wc-retailcrm-proxy.php' );
+ }
+
+ $this->retailcrm = new WC_Retailcrm_Proxy(
+ $this->retailcrm_settings['api_url'],
+ $this->retailcrm_settings['api_key']
+ );
+
+ $this->startDate = new DateTime(date('Y-m-d H:i:s', strtotime('-1 days', strtotime(date('Y-m-d H:i:s')))));
+ $this->startDateOrders = $this->startDate;
+ $this->startDateCustomers = $this->startDate;
+ }
+
+ public function getHistory()
+ {
+ if (isset($this->retailcrm_settings['history_orders'])) {
+ $this->startDateOrders = new DateTime($this->retailcrm_settings['history_orders']);
+ }
+
+ if (isset($this->retailcrm_settings['history_customers'])) {
+ $this->startDateCustomers = new DateTime($this->retailcrm_settings['history_orders']);
+ }
+
+ $this->ordersHistory($this->startDateOrders->format('Y-m-d H:i:s'));
+
+ $this->customersHistory($this->startDateCustomers->format('Y-m-d H:i:s'));
+
+ }
+
+ protected function customersHistory($date)
+ {
+ $response = $this->retailcrm->customersHistory(array('startDate' => $date));
+
+ if ($response->isSuccessful()) {
+ $generatedAt = $response->generatedAt;
+
+ foreach ($response['history'] as $record) {
+
+ $this->removeFuncsHook();
+
+ if ($record['field'] == 'first_name' && $record['customer']['externalId']) {
+ if ($record['newValue']){
+ update_user_meta($record['customer']['externalId'], 'first_name', $record['newValue']);
+ }
+ }
+
+ elseif ($record['field'] == 'last_name' && $record['customer']['externalId']) {
+ if ($record['newValue']){
+ update_user_meta($record['customer']['externalId'], 'last_name', $record['newValue']);
+ }
+ }
+
+ elseif ($record['field'] == 'email' && $record['customer']['externalId']) {
+ if ($record['newValue']){
+ update_user_meta($record['customer']['externalId'], 'billing_email', $record['newValue']);
+ }
+ }
+
+ elseif ($record['field'] == 'phones' && $record['customer']['externalId']) {
+ if ($record['newValue']){
+ update_user_meta($record['customer']['externalId'], 'billing_phone', $record['newValue']);
+ }
+ }
+
+ elseif ($record['field'] == 'address.region' && $record['customer']['externalId']) {
+ if ($record['newValue']){
+ update_user_meta($record['customer']['externalId'], 'billing_state', $record['newValue']);
+ }
+ }
+
+ elseif ($record['field'] == 'address.index' && $record['customer']['externalId']) {
+ if ($record['newValue']){
+ update_user_meta($record['customer']['externalId'], 'billing_postcode', $record['newValue']);
+ }
+ }
+
+ elseif ($record['field'] == 'address.country' && $record['customer']['externalId']) {
+ if ($record['newValue']){
+ update_user_meta($record['customer']['externalId'], 'billing_country', $record['newValue']);
+ }
+ }
+
+ elseif ($record['field'] == 'address.city' && $record['customer']['externalId']) {
+ if ($record['newValue']){
+ update_user_meta($record['customer']['externalId'], 'billing_city', $record['newValue']);
+ }
+ }
+
+ $this->addFuncsHook();
+ }
+
+ }
+
+ if (empty($response)) {
+ return;
+ }
+
+ $this->retailcrm_settings['history_customers'] = $generatedAt;
+ update_option('woocommerce_integration-retailcrm_settings', $this->retailcrm_settings);
+ }
+
+ protected function ordersHistory($date)
+ {
+ $options = array_flip(array_filter($this->retailcrm_settings));
+
+ $response = $this->retailcrm->ordersHistory(array('startDate' => $date));
+
+ if ($response->isSuccessful()) {
+
+ $generatedAt = $response->generatedAt;
+
+ foreach ($response['history'] as $record) {
+
+ $this->removeFuncsHook();
+
+ if ($record['field'] == 'status' && !empty($record['newValue']) && !empty($record['oldValue'])) {
+ $newStatus = $record['newValue']['code'];
+ if (!empty($options[$newStatus]) && !empty($record['order']['externalId'])) {
+ $order = new WC_Order($record['order']['externalId']);
+ $order->update_status($options[$newStatus]);
+ }
+ }
+
+ elseif($record['field'] == 'order_product' && $record['newValue']) {
+ $product = wc_get_product($record['item']['offer']['externalId']);
+ $order = new WC_Order($record['order']['externalId']);
+ $order->add_product($product, $record['item']['quantity']);
+
+ $this->update_total($order);
+ }
+
+ elseif($record['field'] == 'order_product.quantity' && $record['newValue']) {
+ $order = new WC_Order($record['order']['externalId']);
+ $product = wc_get_product($record['item']['offer']['externalId']);
+ $items = $order->get_items();
+ $args = array('qty' => $record['newValue']);
+
+ foreach ($items as $order_item_id => $item) {
+ if ($item['variation_id'] != 0 ) {
+ $offer_id = $item['variation_id'];
+ } else {
+ $offer_id = $item['product_id'];
+ }
+ if ($offer_id == $record['item']['offer']['externalId']) {
+ $order->update_product($order_item_id, $product, $args);
+
+ $this->update_total($order);
+ }
+ }
+ }
+
+ elseif ($record['field'] == 'order_product' && !$record['newValue']) {
+ $order = new WC_Order($record['order']['externalId']);
+ $items = $order->get_items();
+
+ foreach ($items as $order_item_id => $item) {
+ if ($item['variation_id'] != 0 ) {
+ $offer_id = $item['variation_id'];
+ } else {
+ $offer_id = $item['product_id'];
+ }
+ if ($offer_id == $record['item']['offer']['externalId']) {
+ wc_delete_order_item($order_item_id);
+
+ $this->update_total($order);
+ }
+ }
+ }
+
+ elseif ($record['field'] == 'delivery_type') {
+ $newValue = $record['newValue']['code'];
+ if (!empty($options[$newValue]) && !empty($record['order']['externalId'])) {
+ $order = new WC_Order($record['order']['externalId']);
+ $items = $order->get_items('shipping');
+ $wc_shipping = new WC_Shipping();
+ $wc_shipping_list = $wc_shipping->get_shipping_methods();
+
+ foreach ($wc_shipping_list as $method) {
+ if ($method->id == $options[$newValue]) {
+ $deliveryCost = $method->cost;
+ }
+ }
+
+ $item_id = $this->getShippingItemId($items);
+ $args = array(
+ 'method_id' => $options[$newValue],
+ 'cost' => $deliveryCost ? $deliveryCost : 0
+ );
+ $order->update_shipping( $item_id, $args );
+
+ $this->update_total($order);
+ }
+ }
+
+ elseif ($record['field'] == 'delivery_address.region') {
+ $order = new WC_Order($record['order']['externalId']);
+ $address = array(
+ 'state' => $record['newValue']
+ );
+ $order->set_address($address, 'shipping');
+ }
+
+ elseif ($record['field'] == 'delivery_address.city') {
+ $order = new WC_Order($record['order']['externalId']);
+ $address = array(
+ 'city' => $record['newValue']
+ );
+ $order->set_address($address, 'shipping');
+ }
+
+ elseif ($record['field'] == 'delivery_address.street') {
+ $order = new WC_Order($record['order']['externalId']);
+ $address = array(
+ 'address_1' => $record['newValue']
+ );
+ $order->set_address($address, 'shipping');
+ }
+
+ elseif ($record['field'] == 'delivery_address.building') {
+ $order = new WC_Order($record['order']['externalId']);
+ $address = array(
+ 'address_2' => $record['newValue']
+ );
+ $order->set_address($address, 'shipping');
+ }
+
+ elseif ($record['field'] == 'payment_type') {
+ $order = new WC_Order($record['order']['externalId']);
+ $newValue = $record['newValue']['code'];
+ if (!empty($options[$newValue]) && !empty($record['order']['externalId'])) {
+ $payment = new WC_Payment_Gateways();
+ $payment_types = $payment->get_available_payment_gateways();
+ if (isset($payment_types[$options[$newValue]])) {
+ $order->set_payment_method($payment_types[$options[$newValue]]);
+ }
+ }
+ }
+
+ elseif (isset($record['created']) &&
+ $record['created'] == 1 &&
+ !isset($record['order']['externalId'])) {
+
+ $args = array(
+ 'status' => $options[$record['order']['status']],
+ 'customer_id' => isset($record['order']['customer']['externalId']) ?
+ $record['order']['customer']['externalId'] :
+ null
+ );
+
+ $order_record = $record['order'];
+ $order_data = wc_create_order($args);
+ $order = new WC_Order($order_data->id);
+
+ $address_shipping = array(
+ 'first_name' => $order_record['firstName'],
+ 'last_name' => $order_record['lastName'],
+ 'company' => '',
+ 'email' => $order_record['email'],
+ 'phone' => $order_record['phone'],
+ 'address_1' => $order_record['delivery']['address']['text'],
+ 'address_2' => '',
+ 'city' => $order_record['delivery']['address']['city'],
+ 'state' => $order_record['delivery']['address']['region'],
+ 'postcode' => isset($order_record['delivery']['address']['postcode']) ? $order_record['delivery']['address']['postcode'] : '',
+ 'country' => $order_record['delivery']['address']['countryIso']
+ );
+ $address_billing = array(
+ 'first_name' => $order_record['customer']['firstName'],
+ 'last_name' => $order_record['customer']['lastName'],
+ 'company' => '',
+ 'email' => $order_record['customer']['email'],
+ 'phone' => $order_record['customer'][0]['number'],
+ 'address_1' => $order_record['customer']['address']['text'],
+ 'address_2' => '',
+ 'city' => $order_record['customer']['address']['city'],
+ 'state' => $order_record['customer']['address']['region'],
+ 'postcode' => isset($order_record['customer']['address']['postcode']) ? $order_record['customer']['address']['postcode'] : '',
+ 'country' => $order_record['customer']['address']['countryIso']
+ );
+
+ if ($order_record['paymentType']) {
+ $payment = new WC_Payment_Gateways();
+ $payment_types = $payment->get_available_payment_gateways();
+ if (isset($payment_types[$options[$order_record['paymentType']]])) {
+ $order->set_payment_method($payment_types[$options[$order_record['paymentType']]]);
+ }
+ }
+
+ $order->set_address($address_billing, 'billing');
+ $order->set_address($address_shipping, 'shipping');
+ $product_data = $order_record['items'];
+
+ foreach ($product_data as $product) {
+ $order->add_product(wc_get_product($product['offer']['externalId']), $product['quantity']);
+ }
+
+ $wc_shipping = new WC_Shipping();
+ $wc_shipping_types = $wc_shipping->get_shipping_methods();
+
+ foreach ($wc_shipping_types as $shipping_type) {
+ if ($shipping_type->id == $options[$order_record['delivery']['code']]) {
+ $shipping_method_id = $shipping_type->id;
+ $shipping_method_title = $shipping_type->title;
+ $shipping_total = $shipping_type->cost;
+ }
+ }
+
+ $shipping_rate = new WC_Shipping_Rate($shipping_method_id, isset($shipping_method_title) ? $shipping_method_title : '', isset($shipping_total) ? floatval($shipping_total) : 0, array(), $shipping_method_id);
+ $order->add_shipping($shipping_rate);
+
+ $this->update_total($order);
+
+ $ids[] = array(
+ 'id' => (int)$order_record['id'],
+ 'externalId' => (int)$order_data->id
+ );
+
+ $this->retailcrm->ordersFixExternalIds($ids);
+ }
+
+ $this->addFuncsHook();
+ }
+
+ }
+
+ if (empty($response)) {
+ return;
+ }
+
+ $this->retailcrm_settings['history_orders'] = $generatedAt;
+ update_option('woocommerce_integration-retailcrm_settings', $this->retailcrm_settings);
+
+ }
+
+ protected function removeFuncsHook()
+ {
+ remove_action('woocommerce_order_status_changed', 'retailcrm_update_order_status', 11, 1);
+ remove_action('woocommerce_saved_order_items', 'retailcrm_update_order_items', 10, 2);
+ remove_action('update_post_meta', 'retailcrm_update_order', 11, 4);
+ remove_action('woocommerce_payment_complete', 'retailcrm_update_order_payment', 11, 1);
+ remove_action('woocommerce_checkout_update_user_meta', 'update_customer', 10, 2);
+ }
+
+ protected function addFuncsHook()
+ {
+ if (!has_action('woocommerce_checkout_update_user_meta', 'update_customer')) {
+ add_action('woocommerce_checkout_update_user_meta', 'update_customer', 10, 2);
+ }
+ if (!has_action('woocommerce_order_status_changed', 'retailcrm_update_order_status')) {
+ add_action('woocommerce_order_status_changed', 'retailcrm_update_order_status', 11, 1);
+ }
+ if (!has_action('woocommerce_saved_order_items', 'retailcrm_update_order_items')) {
+ add_action('woocommerce_saved_order_items', 'retailcrm_update_order_items', 10, 2);
+ }
+ if (!has_action('update_post_meta', 'retailcrm_update_order')) {
+ add_action('update_post_meta', 'retailcrm_update_order', 11, 4);
+ }
+ if (!has_action('woocommerce_payment_complete', 'retailcrm_update_order_payment')) {
+ add_action('woocommerce_payment_complete', 'retailcrm_update_order_payment', 11, 1);
+ }
+ }
+
+ protected function getShippingItemId($items)
+ {
+ if ($items) {
+
+ foreach ($items as $key => $value) {
+ $item_id[] = $key;
+ }
+ }
+
+ return $item_id[0];
+ }
+
+
+ protected function update_total($order)
+ {
+ $order->update_taxes();
+ $order->calculate_totals();
+ }
+ }
+endif;
diff --git a/retailcrm/include/class-wc-retailcrm-icml.php b/retailcrm/include/class-wc-retailcrm-icml.php
new file mode 100644
index 0000000..e852a3f
--- /dev/null
+++ b/retailcrm/include/class-wc-retailcrm-icml.php
@@ -0,0 +1,461 @@
+shop = get_bloginfo( 'name' );
+ $this->file = ABSPATH . 'retailcrm.xml';
+ $this->tmpFile = sprintf('%s.tmp', $this->file);
+ }
+
+ /**
+ * Generate file
+ */
+ public function generate()
+ {
+ $categories = $this->get_wc_categories_taxonomies();
+ $offers = $this->get_wc_products_taxonomies();
+
+ if (file_exists($this->tmpFile)) {
+ if (filectime($this->tmpFile) + $this->fileLifeTime < time()) {
+ unlink($this->tmpFile);
+ $this->writeHead();
+ }
+ } else {
+ $this->writeHead();
+ }
+
+ try {
+ if (!empty($categories)) {
+ $this->writeCategories($categories);
+ unset($categories);
+ }
+
+ if (!empty($offers)) {
+ $this->writeOffers($offers);
+ unset($offers);
+ }
+
+ $dom = dom_import_simplexml(simplexml_load_file($this->tmpFile))->ownerDocument;
+ $dom->formatOutput = true;
+ $formatted = $dom->saveXML();
+
+ unset($dom, $this->xml);
+
+ file_put_contents($this->tmpFile, $formatted);
+ rename($this->tmpFile, $this->file);
+ } catch (Exception $e) {
+ unlink($this->tmpFile);
+ }
+ }
+
+ /**
+ * Load tmp data
+ *
+ * @return \SimpleXMLElement
+ */
+ private function loadXml()
+ {
+ return new SimpleXMLElement(
+ $this->tmpFile,
+ LIBXML_NOENT | LIBXML_NOCDATA | LIBXML_COMPACT | LIBXML_PARSEHUGE,
+ true
+ );
+ }
+
+ /**
+ * Generate xml header
+ */
+ private function writeHead()
+ {
+ $string = sprintf(
+ '%s',
+ date('Y-m-d H:i:s'),
+ $this->shop
+ );
+
+ file_put_contents($this->tmpFile, $string, LOCK_EX);
+ }
+
+ /**
+ * Write categories in file
+ *
+ * @param $categories
+ */
+ private function writeCategories($categories)
+ {
+ $chunkCategories = array_chunk($categories, $this->chunk);
+ foreach ($chunkCategories as $categories) {
+ $this->xml = $this->loadXml();
+
+ $this->categories = $this->xml->shop->categories;
+ $this->addCategories($categories);
+
+ $this->xml->asXML($this->tmpFile);
+ }
+
+ unset($this->categories);
+ }
+
+ /**
+ * Write products in file
+ *
+ * @param $offers
+ */
+ private function writeOffers($offers)
+ {
+ $chunkOffers = array_chunk($offers, $this->chunk);
+ foreach ($chunkOffers as $offers) {
+ $this->xml = $this->loadXml();
+
+ $this->offers = $this->xml->shop->offers;
+ $this->addOffers($offers);
+
+ $this->xml->asXML($this->tmpFile);
+ }
+
+ unset($this->offers);
+ }
+
+ /**
+ * Add categories
+ *
+ * @param $categories
+ */
+ private function addCategories($categories)
+ {
+ $categories = self::filterRecursive($categories);
+
+ foreach($categories as $category) {
+ if (!array_key_exists('name', $category) || !array_key_exists('id', $category)) {
+ continue;
+ }
+
+ /** @var SimpleXMLElement $e */
+ /** @var SimpleXMLElement $cat */
+
+ $cat = $this->categories;
+ $e = $cat->addChild('category', $category['name']);
+
+ $e->addAttribute('id', $category['id']);
+
+ if (array_key_exists('parentId', $category) && $category['parentId'] > 0) {
+ $e->addAttribute('parentId', $category['parentId']);
+ }
+ }
+ }
+
+ /**
+ * Add offers
+ *
+ * @param $offers
+ */
+ private function addOffers($offers)
+ {
+ $offers = self::filterRecursive($offers);
+
+ foreach ($offers as $key => $offer) {
+
+ if (!array_key_exists('id', $offer)) {
+ continue;
+ }
+
+ $e = $this->offers->addChild('offer');
+
+ $e->addAttribute('id', $offer['id']);
+
+ if (!array_key_exists('productId', $offer) || empty($offer['productId'])) {
+ $offer['productId'] = $offer['id'];
+ }
+ $e->addAttribute('productId', $offer['productId']);
+
+ if (!empty($offer['quantity'])) {
+ $e->addAttribute('quantity', (int) $offer['quantity']);
+ } else {
+ $e->addAttribute('quantity', 0);
+ }
+
+ if (isset($offer['categoryId']) && $offer['categoryId']) {
+ if (is_array($offer['categoryId'])) {
+ foreach ($offer['categoryId'] as $categoryId) {
+ $e->addChild('categoryId', $categoryId);
+ }
+ } else {
+ $e->addChild('categoryId', $offer['categoryId']);
+ }
+ }
+
+ if (!array_key_exists('name', $offer) || empty($offer['name'])) {
+ $offer['name'] = 'Без названия';
+ }
+
+ if (!array_key_exists('productName', $offer) || empty($offer['productName'])) {
+ $offer['productName'] = $offer['name'];
+ }
+
+ unset($offer['id'], $offer['productId'], $offer['categoryId'], $offer['quantity']);
+ array_walk($offer, array($this, 'setOffersProperties'), $e);
+
+ if (array_key_exists('params', $offer) && !empty($offer['params'])) {
+ array_walk($offer['params'], array($this, 'setOffersParams'), $e);
+ }
+
+ unset($offers[$key]);
+ }
+ }
+
+ /**
+ * Set offer properties
+ *
+ * @param $value
+ * @param $key
+ * @param $e
+ */
+ private function setOffersProperties($value, $key, &$e) {
+ if (in_array($key, $this->properties) && $key != 'params') {
+ /** @var SimpleXMLElement $e */
+ $e->addChild($key, htmlspecialchars($value));
+ }
+ }
+
+ /**
+ * Set offer params
+ *
+ * @param $value
+ * @param $key
+ * @param $e
+ */
+ private function setOffersParams($value, $key, &$e) {
+ if (
+ array_key_exists('code', $value) &&
+ array_key_exists('name', $value) &&
+ array_key_exists('value', $value) &&
+ !empty($value['code']) &&
+ !empty($value['name']) &&
+ !empty($value['value'])
+ ) {
+ /** @var SimpleXMLElement $e */
+ $param = $e->addChild('param', htmlspecialchars($value['value']));
+ $param->addAttribute('code', $value['code']);
+ $param->addAttribute('name', substr(htmlspecialchars($value['name']), 0, 200));
+ unset($key);
+ }
+ }
+
+ /**
+ * Filter result array
+ *
+ * @param $haystack
+ *
+ * @return mixed
+ */
+ public static function filterRecursive($haystack)
+ {
+ foreach ($haystack as $key => $value) {
+ if (is_array($value)) {
+ $haystack[$key] = self::filterRecursive($haystack[$key]);
+ }
+
+ if (is_null($haystack[$key]) || $haystack[$key] === '' || count($haystack[$key]) == 0) {
+ unset($haystack[$key]);
+ } elseif (!is_array($value)) {
+ $haystack[$key] = trim($value);
+ }
+ }
+
+ return $haystack;
+ }
+
+ /**
+ * Get WC products
+ *
+ * @return array
+ */
+ private function get_wc_products_taxonomies() {
+ $full_product_list = array();
+ $loop = new WP_Query(array('post_type' => array('product', 'product_variation'), 'posts_per_page' => -1));
+
+ while ($loop->have_posts()) : $loop->the_post();
+ $theid = get_the_ID();
+ if ( version_compare( get_option( 'woocommerce_db_version' ), '3.0', '<' ) ) {
+ $product = new WC_Product($theid);
+ $parent = new WC_Product($product->get_parent());
+ }
+ else {
+ if (get_post_type($theid) == 'product') {
+ $product = new WC_Product_Simple($theid);
+ }
+ elseif (get_post_type($theid) == 'product_variation') {
+ $post = get_post($theid);
+
+ if (get_post($post->post_parent)) {
+ $product = new WC_Product_Variation($theid);
+ $parent = new WC_Product_Simple($product->get_parent_id());
+ }
+ }
+ }
+
+ if ($this->get_parent_product($product) > 0) {
+ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $parent->get_id() ), 'single-post-thumbnail' );
+ $term_list = wp_get_post_terms($parent->get_id(), 'product_cat', array('fields' => 'ids'));
+ $attributes = get_post_meta( $parent->get_id() , '_product_attributes' );
+ } else {
+ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $theid ), 'single-post-thumbnail' );
+ $term_list = wp_get_post_terms($product->get_id(), 'product_cat', array('fields' => 'ids'));
+ $attributes = get_post_meta( $product->get_id() , '_product_attributes' );
+ }
+
+ $attributes = (isset($attributes[0])) ? $attributes[0] : $attributes;
+
+ $params = array();
+
+ $weight = $product->get_weight();
+
+ if (!empty($weight)) {
+ $params[] = array('code' => 'weight', 'name' => 'Weight', 'value' => $weight);
+ }
+
+ if (!empty($attributes)) {
+ foreach ($attributes as $attribute_name => $attribute) {
+ $attributeValue = get_post_meta($product->get_id(), 'attribute_'.$attribute_name);
+ $attributeValue = end($attributeValue);
+ if ($attribute['is_visible'] == 1 && !empty($attribute['value'])) {
+ $params[] = array(
+ 'code' => $attribute_name,
+ 'name' => $attribute['name'],
+ 'value' => $attributeValue
+ );
+ }
+ }
+ }
+
+ if ($product->get_sku() != '') {
+ $params[] = array('code' => 'sku', 'name' => 'SKU', 'value' => $product->get_sku());
+ }
+
+ $product_data = array(
+ 'id' => $product->get_id(),
+ 'productId' => ($this->get_parent_product($product) > 0) ? $parent->get_id() : $product->get_id(),
+ 'name' => $product->get_title(),
+ 'productName' => ($this->get_parent_product($product) > 0) ? $parent->get_title() : $product->get_title(),
+ 'price' => $this->get_price_with_tax($product),
+ 'purchasePrice' => $product->get_regular_price(),
+ 'picture' => $image[0],
+ 'url' => ($this->get_parent_product($product) > 0) ? $parent->get_permalink() : $product->get_permalink(),
+ 'quantity' => is_null($product->get_stock_quantity()) ? 0 : $product->get_stock_quantity(),
+ 'categoryId' => $term_list
+ );
+
+ if (!empty($params)) {
+ $product_data['params'] = $params;
+ }
+
+ $full_product_list[] = $product_data;
+ unset($product_data);
+ endwhile;
+
+ return $full_product_list;
+ }
+
+ /**
+ * Get WC categories
+ *
+ * @return array
+ */
+ private function get_wc_categories_taxonomies() {
+ $categories = array();
+ $taxonomy = 'product_cat';
+ $orderby = 'parent';
+ $show_count = 0; // 1 for yes, 0 for no
+ $pad_counts = 0; // 1 for yes, 0 for no
+ $hierarchical = 1; // 1 for yes, 0 for no
+ $title = '';
+ $empty = 0;
+
+ $args = array(
+ 'taxonomy' => $taxonomy,
+ 'orderby' => $orderby,
+ 'show_count' => $show_count,
+ 'pad_counts' => $pad_counts,
+ 'hierarchical' => $hierarchical,
+ 'title_li' => $title,
+ 'hide_empty' => $empty
+ );
+
+ $wcatTerms = get_categories( $args );
+
+ foreach ($wcatTerms as $term) {
+ $categories[] = array(
+ 'id' => $term->term_id,
+ 'parentId' => $term->parent,
+ 'name' => $term->name
+ );
+ }
+
+ return $categories;
+ }
+
+ private function get_parent_product($product) {
+ global $woocommerce;
+ if ( version_compare( $woocommerce->version, '3.0', '<' ) ) {
+ return $product->get_parent();
+ } else {
+ return $product->get_parent_id();
+ }
+ }
+
+ private function get_price_with_tax($product) {
+ global $woocommerce;
+ if ( version_compare( $woocommerce->version, '3.0', '<' ) ) {
+ return $product->get_price_including_tax();
+ } else {
+ return wc_get_price_including_tax($product);
+ }
+ }
+ }
+
+endif;
diff --git a/retailcrm/include/class-wc-retailcrm-inventories.php b/retailcrm/include/class-wc-retailcrm-inventories.php
new file mode 100644
index 0000000..f4a5efc
--- /dev/null
+++ b/retailcrm/include/class-wc-retailcrm-inventories.php
@@ -0,0 +1,75 @@
+retailcrm_settings = get_option( 'woocommerce_integration-retailcrm_settings' );
+
+ if ( ! class_exists( 'WC_Retailcrm_Proxy' ) ) {
+ include_once( __DIR__ . '/api/class-wc-retailcrm-proxy.php' );
+ }
+
+ $this->retailcrm = new WC_Retailcrm_Proxy(
+ $this->retailcrm_settings['api_url'],
+ $this->retailcrm_settings['api_key']
+ );
+ }
+
+ public function load_stocks()
+ {
+ $page = 1;
+
+ do {
+ $result = $this->retailcrm->storeInventories(array(), $page, 250);
+ $totalPageCount = $result['pagination']['totalPageCount'];
+ $page++;
+
+ foreach ($result['offers'] as $offer) {
+ if (isset($offer['externalId'])) {
+ $post = get_post($offer['externalId']);
+
+ if ($post->post_type == 'product') {
+ $product = new WC_Product_Simple($offer['externalId']);
+ update_post_meta($offer['externalId'], '_manage_stock', 'yes');
+ $product->set_stock($offer['quantity']);
+ } elseif ($post->post_type == 'product_variation') {
+ $args = array();
+ if ($post->post_parent) {
+ $args['parent_id'] = $post->post_parent;
+ $args['parent'] = new WC_Product_Simple($post->post_parent);
+ }
+ $product = new WC_Product_Variation($offer['externalId'], $args);
+ update_post_meta($offer['externalId'], '_manage_stock', 'yes');
+ $product->set_stock($offer['quantity']);
+ }
+ }
+ }
+
+ } while ($page < $totalPageCount);
+ }
+
+ public function updateQuantity()
+ {
+ $options = array_filter(get_option( 'woocommerce_integration-retailcrm_settings' ));
+
+ if ($options['sync'] == 'yes') {
+ $this->load_stocks();
+ } else {
+ return false;
+ }
+ }
+ }
+endif;
diff --git a/retailcrm/include/class-wc-retailcrm-orders.php b/retailcrm/include/class-wc-retailcrm-orders.php
new file mode 100644
index 0000000..887e170
--- /dev/null
+++ b/retailcrm/include/class-wc-retailcrm-orders.php
@@ -0,0 +1,284 @@
+retailcrm_settings = get_option( 'woocommerce_integration-retailcrm_settings' );
+
+ if ( ! class_exists( 'WC_Retailcrm_Proxy' ) ) {
+ include_once( __DIR__ . '/api/class-wc-retailcrm-proxy.php' );
+ }
+
+ $this->retailcrm = new WC_Retailcrm_Proxy(
+ $this->retailcrm_settings['api_url'],
+ $this->retailcrm_settings['api_key']
+ );
+ }
+
+ /**
+ * Upload orders to CRM
+ */
+ public function ordersUpload()
+ {
+ $orders = get_posts(array(
+ 'numberposts' => -1,
+ 'post_type' => wc_get_order_types('view-orders'),
+ 'post_status' => array_keys(wc_get_order_statuses())
+ ));
+
+ $orders_data = array();
+
+ foreach ($orders as $data_order) {
+ $order_data = $this->processOrder($data_order->ID);
+
+ $order = new WC_Order($order_id);
+ $customer = $order->get_user();
+
+ if ($customer != false) {
+ $order_data['customer']['externalId'] = $customer->get('ID');
+ }
+
+ $orders_data[] = $order_data;
+ }
+
+ $uploadOrders = array_chunk($orders_data, 50);
+
+ foreach ($uploadOrders as $uploadOrder) {
+ $this->retailcrm->ordersUpload($uploadOrder);
+ }
+ }
+
+ /**
+ * Create order
+ *
+ * @param $order_id
+ */
+ public function orderCreate($order_id)
+ {
+ $order_data = $this->processOrder($order_id);
+
+ $order = new WC_Order($order_id);
+ $customer = $order->get_user();
+
+ if ($customer != false) {
+ $search = $this->retailcrm->customersGet($customer->get('ID'));
+
+ if (!$search->isSuccessful()) {
+ $customer_data = array(
+ 'externalId' => $customer->get('ID'),
+ 'firstName' => $order_data['firstName'],
+ 'lastName' => $order_data['lastName'],
+ 'email' => $order_data['email']
+ );
+
+ $this->retailcrm->customersCreate($customer_data);
+
+ } else {
+ $order_data['customer']['externalId'] = $search['customer']['externalId'];
+ }
+ }
+
+ $this->retailcrm->ordersCreate($order_data);
+ }
+
+ /**
+ * Update shipping address
+ *
+ * @param $order_id, $address
+ */
+ public function orderUpdateShippingAddress($order_id, $address) {
+ $address['externalId'] = $order_id;
+
+ $response = $this->retailcrm->ordersEdit($address);
+ }
+
+ /**
+ * Update order status
+ *
+ * @param $order_id
+ */
+ public function orderUpdateStatus($order_id) {
+ $order = new WC_Order( $order_id );
+
+ $order_data = array(
+ 'externalId' => $order_id,
+ 'status' => $this->retailcrm_settings[$order->get_status()]
+ );
+
+ $response = $this->retailcrm->ordersEdit($order_data);
+ }
+
+ /**
+ * Update order payment type
+ *
+ * @param $order_id
+ */
+ public function orderUpdatePaymentType($order_id, $payment_method) {
+
+ $order_data = array(
+ 'externalId' => $order_id,
+ 'paymentType' => $this->retailcrm_settings[$payment_method]
+ );
+
+ $response = $this->retailcrm->ordersEdit($order_data);
+ }
+
+ /**
+ * Update order payment
+ *
+ * @param $order_id
+ */
+ public function orderUpdatePayment($order_id) {
+ $order = new WC_Order( $order_id );
+
+ $order_data = array(
+ 'externalId' => $order_id,
+ 'paymentStatus' => 'paid'
+ );
+
+ $response = $this->retailcrm->ordersEdit($order_data);
+ }
+
+ /**
+ * Update order items
+ *
+ * @param $order_id, $data
+ */
+ public function orderUpdateItems($order_id, $data) {
+ $order = new WC_Order( $order_id );
+
+ $order_data['externalId'] = $order_id;
+ $shipping_method = end($data['shipping_method']);
+ $shipping_cost = end($data['shipping_cost']);
+ $products = $order->get_items();
+ $items = array();
+
+ foreach ($products as $order_item_id => $product) {
+ if ($product['variation_id'] > 0) {
+ $offer_id = $product['variation_id'];
+ } else {
+ $offer_id = $product['product_id'];
+ }
+
+ $_product = wc_get_product($offer_id);
+ $items[] = array(
+ 'offer' => array('externalId' => $offer_id),
+ 'productName' => $product['name'],
+ 'initialPrice' => (float)$_product->get_price(),
+ 'quantity' => $product['qty']
+ );
+ }
+
+ $order_data['items'] = $items;
+
+ if (!empty($shipping_method) && !empty($this->retailcrm_settings[$shipping_method])) {
+ $order_data['delivery']['code'] = $this->retailcrm_settings[$shipping_method];
+ }
+
+ if (!empty($shipping_cost)) {
+ $shipping_cost = str_replace(',', '.', $shipping_cost);
+ $order_data['delivery']['cost'] = $shipping_cost;
+ }
+
+ $response = $this->retailcrm->ordersEdit($order_data);
+ }
+
+ public function processOrder($order_id)
+ {
+ if ( !$order_id ){
+ return;
+ }
+
+ $order = new WC_Order( $order_id );
+ $order_data = array();
+
+ $order_data['externalId'] = $order->id;
+ $order_data['number'] = $order->get_order_number();
+ $order_data['createdAt'] = $order->order_date;
+
+ if (!empty($order->payment_method) && !empty($this->retailcrm_settings[$order->payment_method])) {
+ $order_data['paymentType'] = $this->retailcrm_settings[$order->payment_method];
+ }
+
+ if(!empty($order->get_items( 'shipping' )) && $order->get_items( 'shipping' ) != '') {
+ $shipping = end($order->get_items( 'shipping' ));
+ $shipping_code = explode(':', $shipping['method_id']);
+ $shipping_method = $shipping_code[0];
+ $shipping_cost = $shipping['cost'];
+
+ if (!empty($shipping_method) && !empty($this->retailcrm_settings[$shipping_method])) {
+ $order_data['delivery']['code'] = $this->retailcrm_settings[$shipping_method];
+ }
+
+ if (!empty($shipping_cost)) {
+ $order_data['delivery']['cost'] = $shipping_cost;
+ }
+ }
+
+ if ($order->is_paid()) {
+ $order_data['paymentStatus'] = 'paid';
+ }
+
+ $status = $order->get_status();
+ $order_data['status'] = $this->retailcrm_settings[$status];
+
+ $user_data = $order->get_address();
+
+ if (!empty($user_data)) {
+
+ if (!empty($user_data['first_name'])) $order_data['firstName'] = $user_data['first_name'];
+ if (!empty($user_data['last_name'])) $order_data['lastName'] = $user_data['last_name'];
+ if (!empty($user_data['phone'])) $order_data['phone'] = $user_data['phone'];
+ if (!empty($user_data['email'])) $order_data['email'] = $user_data['email'];
+ if (!empty($user_data['postcode'])) $order_data['delivery']['address']['index'] = $user_data['postcode'];
+ if (!empty($user_data['state'])) $order_data['delivery']['address']['region'] = $user_data['state'];
+ if (!empty($user_data['city'])) $order_data['delivery']['address']['city'] = $user_data['city'];
+ if (!empty($user_data['country'])) $order_data['delivery']['address']['countryIso'] = $user_data['country'];
+
+ $order_data['delivery']['address']['text'] = sprintf(
+ "%s %s %s %s %s",
+ $user_data['postcode'],
+ $user_data['state'],
+ $user_data['city'],
+ $user_data['address_1'],
+ $user_data['address_2']
+ );
+ }
+
+ $order_items = array();
+
+ foreach ($order->get_items() as $item) {
+ $uid = ($item['variation_id'] > 0) ? $item['variation_id'] : $item['product_id'] ;
+ $_product = wc_get_product($uid);
+
+ if ($_product) {
+ $order_item = array(
+ 'offer' => array('externalId' => $uid),
+ 'productName' => $item['name'],
+ 'initialPrice' => (float)$_product->get_price(),
+ 'quantity' => $item['qty'],
+ );
+ }
+
+ $order_items[] = $order_item;
+ }
+
+ $order_data['items'] = $order_items;
+
+ return $order_data;
+ }
+ }
+endif;
diff --git a/retailcrm/include/index.php b/retailcrm/include/index.php
new file mode 100644
index 0000000..e71af0e
--- /dev/null
+++ b/retailcrm/include/index.php
@@ -0,0 +1 @@
+updateQuantity();
+}
+
+/**
+ * Generate ICML file
+ */
+function generate_icml()
+{
+ if ( ! class_exists( 'WC_Retailcrm_Icml' ) ) {
+ include_once( __DIR__ . check_custom_icml() );
+ }
+
+ $icml = new WC_Retailcrm_Icml();
+ $icml->generate();
+}
+
+/**
+ * Create order
+ *
+ * @param $order_id
+ */
+function retailcrm_process_order($order_id)
+{
+ if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
+ include_once( __DIR__ . check_custom_order() );
+ }
+
+ $order_class = new WC_Retailcrm_Orders();
+ $order_class->orderCreate($order_id);
+}
+
+/**
+ * Update order status
+ *
+ * @param $order_id
+ */
+function retailcrm_update_order_status($order_id)
+{
+ if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
+ include_once( __DIR__ . check_custom_order() );
+ }
+
+ $order_class = new WC_Retailcrm_Orders();
+ $order_class->orderUpdateStatus($order_id);
+}
+
+/**
+ * Update order payment
+ *
+ * @param $order_id
+ */
+function retailcrm_update_order_payment($order_id)
+{
+ if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
+ include_once( __DIR__ . check_custom_order() );
+ }
+
+ $order_class = new WC_Retailcrm_Orders();
+ $order_class->orderUpdatePayment($order_id);
+}
+
+/**
+ * Update order
+ *
+ * @param $meta_id, $order_id, $meta_key, $_meta_value
+ */
+function retailcrm_update_order($meta_id, $order_id, $meta_key, $_meta_value)
+{
+ if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
+ include_once( __DIR__ . check_custom_order() );
+ }
+ $order_class = new WC_Retailcrm_Orders();
+
+ if ($meta_key == '_payment_method') {
+ $order_class->orderUpdatePaymentType($order_id, $_meta_value);
+ }
+
+ $address = array();
+
+ if ($meta_key == '_shipping_first_name') $address['firstName'] = $_meta_value;
+ if ($meta_key == '_shipping_last_name') $address['lastName'] = $_meta_value;
+ if ($meta_key == '_billing_phone') $address['phone'] = $_meta_value;
+ if ($meta_key == '_billing_email') $address['email'] = $_meta_value;
+ if ($meta_key == '_shipping_city') $address['delivery']['address']['city'] = $_meta_value;
+ if ($meta_key == '_shipping_state') $address['delivery']['address']['region'] = $_meta_value;
+ if ($meta_key == '_shipping_postcode') $address['delivery']['address']['index'] = $_meta_value;
+ if ($meta_key == '_shipping_country') $address['delivery']['address']['countryIso'] = $_meta_value;
+ if ($meta_key == '_shipping_address_1') $address['delivery']['address']['text'] = $_meta_value;
+ if ($meta_key == '_shipping_address_2') $address['delivery']['address']['text'] .= $_meta_value;
+
+ if (!empty($address)) {
+ $order_class->orderUpdateShippingAddress($order_id, $address);
+ }
+}
+
+/**
+ * Update order items
+ *
+ * @param $order_id, $data
+ */
+function retailcrm_update_order_items($order_id, $data)
+{
+ if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
+ include_once( __DIR__ . check_custom_order() );
+ }
+
+ $order_class = new WC_Retailcrm_Orders();
+ $order_class->orderUpdateItems($order_id, $data);
+}
+
+function retailcrm_history_get()
+{
+ if ( ! class_exists( 'WC_Retailcrm_History' ) ) {
+ include_once( __DIR__ . '/include/class-wc-retailcrm-history.php' );
+ }
+
+ $history_class = new WC_Retailcrm_History();
+ $history_class->getHistory();
+}
+
+function create_customer($customer_id) {
+ if ( ! class_exists( 'WC_Retailcrm_Customers' ) ) {
+ include_once( __DIR__ . '/include/class-wc-retailcrm-customers.php' );
+ }
+
+ $customer_class = new WC_Retailcrm_Customers();
+ $customer_class->createCustomer($customer_id);
+}
+
+function update_customer($customer_id, $data) {
+ if ( ! class_exists( 'WC_Retailcrm_Customers' ) ) {
+ include_once( __DIR__ . '/include/class-wc-retailcrm-customers.php' );
+ }
+
+ $customer_class = new WC_Retailcrm_Customers();
+ $customer_class->updateCustomer($customer_id);
+}
+
+function register_icml_generation() {
+ // Make sure this event hasn't been scheduled
+ if( !wp_next_scheduled( 'retailcrm_icml' ) ) {
+ // Schedule the event
+ wp_schedule_event( time(), 'three_hours', 'retailcrm_icml' );
+ }
+}
+
+function register_retailcrm_history() {
+ // Make sure this event hasn't been scheduled
+ if( !wp_next_scheduled( 'retailcrm_history' ) ) {
+ // Schedule the event
+ wp_schedule_event( time(), 'five_minutes', 'retailcrm_history' );
+ }
+}
+
+function check_inventories() {
+ if( !wp_next_scheduled( 'retailcrm_inventories' ) ) {
+ // Schedule the event
+ wp_schedule_event( time(), 'fiveteen_minutes', 'retailcrm_inventories' );
+ }
+}
+
+function filter_cron_schedules($param) {
+ return array(
+ 'five_minutes' => array(
+ 'interval' => 300, // seconds
+ 'display' => __('Every 5 minutes')
+ ),
+ 'three_hours' => array(
+ 'interval' => 10800, // seconds
+ 'display' => __('Every 3 hours')
+ ),
+ 'fiveteen_minutes' => array(
+ 'interval' => 900, // seconds
+ 'display' => __('Every 1 hour')
+ )
+ );
+}
+
+function upload_to_crm() {
+ if ( ! class_exists( 'WC_Retailcrm_Orders' ) ) {
+ include_once( __DIR__ . check_custom_order() );
+ }
+
+ if ( ! class_exists( 'WC_Retailcrm_Customers' ) ) {
+ include_once( __DIR__ . '/include/class-wc-retailcrm-customers.php' );
+ }
+
+ $options = array_filter(get_option( 'woocommerce_integration-retailcrm_settings' ));
+
+ if ($options['uploadToCrm'] == 'yes' && !isset($options['uploaded'])) {
+ $options['uploadToCrm'] = 'no';
+ $options['uploaded'] = 'yes';
+
+ $orders = new WC_Retailcrm_Orders();
+ $customers = new WC_Retailcrm_Customers();
+ $customers->customersUpload();
+ $orders->ordersUpload();
+
+ update_option('woocommerce_integration-retailcrm_settings', $options);
+ }
+
+ if (isset($options['uploaded'])) {
+ $options['uploadToCrm'] = 'no';
+ update_option('woocommerce_integration-retailcrm_settings', $options);
+ }
+}
+
+function ajax_upload() {
+ $ajax_url = admin_url('admin-ajax.php');
+ ?>
+
+