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'); + ?> + +