From 37d448f701ff986ef560c2591534a5b30ba587e5 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Thu, 17 Mar 2016 00:54:42 +0300 Subject: [PATCH] pip ready, update for latest api --- .gitignore | 3 +- README.md | 25 +- retailcrm/__init__.py | 221 +-------------- retailcrm/client.py | 642 ++++++++++++++++++++++++++++++++++++++++++ retailcrm/response.py | 29 ++ retailcrm/version.py | 2 - setup.py | 18 +- test.py | 23 -- 8 files changed, 694 insertions(+), 269 deletions(-) create mode 100644 retailcrm/client.py create mode 100644 retailcrm/response.py delete mode 100644 retailcrm/version.py delete mode 100644 test.py diff --git a/.gitignore b/.gitignore index 9c4777b..dc1ff5a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.swp *.pyc -try.py +/*.egg-info +/dist/ diff --git a/README.md b/README.md index 725bc5a..27d3c97 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,19 @@ -api-client-python -================= +retailCRM API python client +=========================== -RetailCrm REST API client (python version) - -##Setup +### Install ``` -git clone https://github.com/retailcrm/api-client-python.git -cd api-client-python -pip install requests -python setup.py install +pip install retailcrm ``` -##Usage +### Usage ```python -from retailcrm import Client +import retailcrm -crm = Client('https://demo.intarocrm.ru', 'uLxXKBwjQteE9NkO3cJAqTXNwvKktaTc') +client = retailcrm.Client('https://demo.intarocrm.ru', 'uLxXKBwjQteE9NkO3cJAqTXNwvKktaTc') order = { 'firstName': 'Ivan', @@ -28,5 +23,9 @@ order = { 'orderMethod': 'call-request', } -result = crm.orderCreate(order) +result = crm.orders_create(order) ``` + +### Documentation + +* http://www.retailcrm.pro/docs/Developers/ApiVersion3 diff --git a/retailcrm/__init__.py b/retailcrm/__init__.py index d439351..e84d0e5 100644 --- a/retailcrm/__init__.py +++ b/retailcrm/__init__.py @@ -1,219 +1,2 @@ -import requests -import json - - -class Client: - """RetailCrm API client""" - - apiVersion = '3' - - def __init__(self, crmUrl, apiKey): - self.apiUrl = crmUrl + '/api/v' + self.apiVersion + '/' - self.apiKey = apiKey - self.parameters = {'apiKey': apiKey} - - def requestApi(self, url, method='GET', format='json'): - - # TODO: catch http exceptions - if method == 'GET': - result = requests.get(url, params=self.parameters) - elif method == 'POST': - result = requests.post(url, data=self.parameters) - - statusCode = result.status_code - r = result.json() - - # reset params dict - self.parameters = {'apiKey': self.apiKey} - - if statusCode > 400 or r.has_key('success') and r['success'] == False: - #TODO: raise ApiException - pass - - if r.has_key('generatedAt'): - self.generatedAt = r['generatedAt'] - del r['generatedAt'] - - del r['success'] - - return r - - def getErrorMessage(self, response): - if type(response) is not dict: return '' - err = '' - - if response.has_key('message'): - err = response['message'] - elif response.has_key('error'): - err = response['error']['message'] - elif response.has_key('errorMsg'): - err = response['errorMsg'] - - if len(err) == 0: return 'Application Error' - - return err - - def orderGet(self, id, by='externalId'): - url = self.apiUrl + 'orders/' + str(id) - - if by != 'externalId': - self.parameters['by'] = by - - return self.requestApi(url) - - def orderCreate(self, order): - dataJson = json.dumps(order) - self.parameters['order'] = dataJson - - url = self.apiUrl + 'orders/create' - return self.requestApi(url, 'POST') - - def orderEdit(self, order): - dataJson = json.dumps(order) - self.parameters['order'] = dataJson - - url = self.apiUrl + 'orders/' + str(order['externalId']) + '/edit' - return self.requestApi(url, 'POST') - - def orderUpload(self, orders): - dataJson = json.dumps(orders) - self.parameters['orders'] = dataJson - - url = self.apiUrl + 'orders/' + str(order['externalId']) + '/edit' - result = self.requestApi(url, 'POST') - - if type(result) is dict and result.has_key('uploadedOrders'): - return result['uploadedOrders'] - else: - return result - - def orderFixExternalIds(self, orders): - dataJson = json.dumps(orders) - self.parameters['orders'] = dataJson - - url = self.apiUrl + 'orders/fix-external-ids' - return self.requestApi(url, 'POST') - - def orderHistory(self, startDate='', endDate='', limit=100, offset=0): - url = self.apiUrl + 'orders/history' - self.parameters['startDate'] = startDate - self.parameters['endDate'] = endDate - self.parameters['limit'] = limit - self.parameters['offset'] = offset - - return self.requestApi(url) - - def customerGet(self, id, by='externalId'): - url = self.apiUrl + 'customers/' + str(id) - - if by != 'externalId': - self.parameters['by'] = by - - return self.requestApi(url) - - def customers(self, phone=None, email=None, fio=None, limit=200, offset=0): - url = self.apiUrl + 'customers' - - if email: - self.parameters['email'] = email - if phone: - self.parameters['phone'] = phone - if fio: - self.parameters['fio'] = fio - - self.parameters['limit'] = limit - self.parameters['offset'] = offset - - return self.requestApi(url) - - def customerCreate(self, customer): - dataJson = json.dumps(customer) - self.parameters['customer'] = dataJson - - url = self.apiUrl + 'customers/create' - return self.requestApi(url, 'POST') - - def customerEdit(self, customer): - dataJson = json.dumps(customer) - self.parameters['customer'] = dataJson - - url = self.apiUrl + 'customers/' + customer['externalId'] + '/edit' - return self.requestApi(url, 'POST') - - def customerUpload(self, customers): - dataJson = json.dumps(customers) - self.parameters['customers'] = dataJson - - url = self.apiUrl + 'customers/upload' - result = self.requestApi(url, 'POST') - - if type(result) is dict and result.has_key('uploaded'): - return result['uploaded'] - else: - return result - - def deliveryTypesList(self): - url = self.apiUrl + 'reference/delivery-types' - return self.requestApi(url) - - def deliveryTypeEdit(self, deliveryType): - dataJson = json.dumps(deliveryType) - self.parameters['deliveryType'] = dataJson - - url = self.apiUrl + 'reference/delivery-types/' + deliveryType['code'] + '/edit' - return self.requestApi(url, 'POST') - - def deliveryServicesList(self): - url = self.apiUrl + 'reference/delivery-services' - return self.requestApi(url) - - def deliveryServiceEdit(self, deliveryService): - dataJson = json.dumps(deliveryService) - self.parameters['deliveryService'] = dataJson - - url = self.apiUrl + 'reference/delivery-services/' + deliveryService['code'] + '/edit' - return self.requestApi(url, 'POST') - - def paymentTypesList(self): - url = self.apiUrl + 'reference/payment-types' - return self.requestApi(url) - - def paymentTypesEdit(self, paymentType): - dataJson = json.dumps(paymentType) - self.parameters['paymentType'] = dataJson - - url = self.apiUrl + 'reference/payment-types/' + paymentType['code'] + '/edit' - return self.requestApi(url, 'POST') - - def orderTypesList(self): - url = self.apiUrl + 'reference/order-types' - return self.requestApi(url) - - def orderTypesEdit(self, orderType): - dataJson = json.dumps(orderType) - self.parameters['orderType'] = dataJson - - url = self.apiUrl + 'reference/order-types/' + orderType['code'] + '/edit' - return self.requestApi(url, 'POST') - - def orderMethodsList(self): - url = self.apiUrl + 'reference/order-methods' - return self.requestApi(url) - - def orderMethodsEdit(self, orderMethod): - dataJson = json.dumps(orderMethod) - self.parameters['orderMethod'] = dataJson - - url = self.apiUrl + 'reference/order-methods/' + orderMethod['code'] + '/edit' - return self.requestApi(url, 'POST') - - def orderStatusesList(self): - url = self.apiUrl + 'reference/statuses' - return self.requestApi(url) - - def orderStatusEdit(self, status): - dataJson = json.dumps(orderStatuse) - self.parameters['status'] = dataJson - - url = self.apiUrl + 'reference/statuses/' + status['code'] + '/edit' - return self.requestApi(url, 'POST') +from client import Client +from response import Response diff --git a/retailcrm/client.py b/retailcrm/client.py new file mode 100644 index 0000000..5eb68a8 --- /dev/null +++ b/retailcrm/client.py @@ -0,0 +1,642 @@ +# coding=utf-8 +import requests +import json +from response import Response + + +class Client(object): + """retailCRM API client""" + + apiVersion = '3' + + def __init__(self, crm_url, api_key): + self.apiUrl = crm_url + '/api/v' + self.apiVersion + '/' + self.apiKey = api_key + self.parameters = {'apiKey': api_key} + + def make_request(self, url, method='GET'): + """ + :param url: string + :param method: string + :return: Response + """ + global result + if method == 'GET': + result = requests.get(url, params=self.parameters) + elif method == 'POST': + result = requests.post(url, data=self.parameters) + + response_code = result.status_code + response_body = result.json() + + return Response(response_code, response_body) + + def orders(self, filters, limit=20, page=1): + """ + :param filters: array + :param limit: integer + :param page: integer + :return: Response + """ + self.parameters['filter'] = filters + self.parameters['limit'] = limit + self.parameters['page'] = page + url = self.apiUrl + 'orders' + + return self.make_request(url) + + def orders_get(self, uid, by='externalId', site=None): + """ + :param uid: string + :param by: string + :param site: string + :return: Response + """ + url = self.apiUrl + 'orders/' + str(uid) + + if site is not None: + self.parameters['site'] = site + + if by != 'externalId': + self.parameters['by'] = by + + return self.make_request(url) + + def orders_create(self, order, site=None): + """ + + :param order: + :param site: + :return: + """ + data_json = json.dumps(order) + self.parameters['order'] = data_json + + if site is not None: + self.parameters['site'] = site + + url = self.apiUrl + 'orders/create' + + return self.make_request(url, 'POST') + + def orders_edit(self, order, site=None): + """ + + :param order: + :param site: + :return: + """ + data_json = json.dumps(order) + self.parameters['order'] = data_json + + if site is not None: + self.parameters['site'] = site + + url = self.apiUrl + 'orders/' + str(order['externalId']) + '/edit' + + return self.make_request(url, 'POST') + + def orders_upload(self, orders, site=None): + """ + + :param orders: + :param site: + :return: + """ + data_json = json.dumps(orders) + self.parameters['orders'] = data_json + + if site is not None: + self.parameters['site'] = site + + url = self.apiUrl + 'orders/upload' + + return self.make_request(url, 'POST') + + def orders_fix_external_ids(self, orders, site=None): + """ + + :param orders: + :param site: + :return: + """ + data_json = json.dumps(orders) + self.parameters['orders'] = data_json + + if site is not None: + self.parameters['site'] = site + + url = self.apiUrl + 'orders/fix-external-ids' + + return self.make_request(url, 'POST') + + def orders_statuses(self, ids, external_ids): + """ + + :param ids: + :param external_ids: + :return: + """ + self.parameters['ids'] = ids + self.parameters['externalIds'] = external_ids + url = self.apiUrl + 'orders/statuses' + + return self.make_request(url) + + def orders_history(self, start_date=None, end_date=None, limit=100, offset=0, skip_my_changes=True): + """ + + :param start_date: + :param end_date: + :param limit: + :param offset: + :param skip_my_changes: + :return: + """ + self.parameters['startDate'] = start_date + self.parameters['endDate'] = end_date + self.parameters['limit'] = limit + self.parameters['offset'] = offset + self.parameters['skipMyChanges'] = skip_my_changes + url = self.apiUrl + 'orders/history' + + return self.make_request(url) + + def customers(self, filters, limit=20, page=0): + """ + + :param filters: + :param limit: + :param page: + :return: + """ + self.parameters['filter'] = filters + self.parameters['limit'] = limit + self.parameters['page'] = page + url = self.apiUrl + 'customers' + + return self.make_request(url) + + def customers_get(self, uid, by='externalId', site=None): + """ + + :param uid: + :param by: + :param site: + :return: + """ + url = self.apiUrl + 'customers/' + str(uid) + + if by != 'externalId': + self.parameters['by'] = by + + if site is not None: + self.parameters['site'] = site + + return self.make_request(url) + + def customers_create(self, customer, site=None): + """ + + :param customer: + :param site: + :return: + """ + data_json = json.dumps(customer) + self.parameters['customer'] = data_json + + if site is not None: + self.parameters['site'] = site + + url = self.apiUrl + 'customers/create' + + return self.make_request(url, 'POST') + + def customers_edit(self, customer, site=None): + """ + + :param customer: + :param site: + :return: + """ + data_json = json.dumps(customer) + self.parameters['customer'] = data_json + + if site is not None: + self.parameters['site'] = site + + url = self.apiUrl + 'customers/' + customer['externalId'] + '/edit' + return self.make_request(url, 'POST') + + def customers_upload(self, customers, site=None): + """ + + :param customers: + :param site: + :return: + """ + data_json = json.dumps(customers) + self.parameters['customers'] = data_json + + if site is not None: + self.parameters['site'] = site + + url = self.apiUrl + 'customers/upload' + + return self.make_request(url, 'POST') + + def customers_fix_external_ids(self, customers, site=None): + """ + + :param customers: + :param site: + :return: + """ + data_json = json.dumps(customers) + self.parameters['customers'] = data_json + + if site is not None: + self.parameters['site'] = site + + url = self.apiUrl + 'customers/fix-external-ids' + + return self.make_request(url, 'POST') + + def inventories(self, filters, limit=20, page=1): + """ + + :param filters: + :param limit: + :param page: + :return: + """ + self.parameters['filter'] = filters + self.parameters['limit'] = limit + self.parameters['page'] = page + url = self.apiUrl + 'store/inventories' + + return self.make_request(url) + + def inventories_upload(self, offers): + """ + + :param offers: + :return: + """ + data_json = json.dumps(offers) + self.parameters['offers'] = data_json + url = self.apiUrl + 'store/inventories/upload' + + return self.make_request(url, 'POST') + + def packs(self, filters, limit=20, page=1): + """ + + :param filters: + :param limit: + :param page: + :return: + """ + self.parameters['filter'] = filters + self.parameters['limit'] = limit + self.parameters['page'] = page + url = self.apiUrl + 'orders/packs' + + return self.make_request(url) + + def packs_get(self, uid): + """ + + :param uid: + :return: + """ + url = self.apiUrl + 'orders/packs/' + str(uid) + + return self.make_request(url) + + def packs_create(self, pack): + """ + + :param pack: + :return: + """ + data_json = json.dumps(pack) + self.parameters['pack'] = data_json + url = self.apiUrl + 'orders/packs/create' + + return self.make_request(url, 'POST') + + def packs_edit(self, pack, uid): + """ + + :param pack: + :param uid: + :return: + """ + data_json = json.dumps(pack) + self.parameters['pack'] = data_json + url = self.apiUrl + 'orders/packs/' + str(uid) + '/edit' + + return self.make_request(url, 'POST') + + def packs_delete(self, uid): + """ + + :param uid: + :return: + """ + url = self.apiUrl + 'orders/packs/' + str(uid) + '/delete' + + return self.make_request(url, 'POST') + + def packs_history(self, filters, limit=20, page=1): + """ + + :param filters: + :param limit: + :param page: + :return: + """ + self.parameters['filter'] = filters + self.parameters['limit'] = limit + self.parameters['page'] = page + url = self.apiUrl + 'orders/packs/history' + + return self.make_request(url) + + def countries(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/countries' + + return self.make_request(url) + + def delivery_types(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/delivery-types' + + return self.make_request(url) + + def delivery_types_edit(self, delivery_type): + """ + + :param delivery_type: + :return: + """ + data_json = json.dumps(delivery_type) + self.parameters['deliveryType'] = data_json + url = self.apiUrl + 'reference/delivery-types/' + delivery_type['code'] + '/edit' + + return self.make_request(url, 'POST') + + def delivery_services(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/delivery-services' + + return self.make_request(url) + + def delivery_services_edit(self, delivery_service): + """ + + :param delivery_service: + :return: + """ + data_json = json.dumps(delivery_service) + self.parameters['deliveryService'] = data_json + url = self.apiUrl + 'reference/delivery-services/' + delivery_service['code'] + '/edit' + + return self.make_request(url, 'POST') + + def payment_types(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/payment-types' + + return self.make_request(url) + + def payment_types_edit(self, payment_type): + """ + + :param payment_type: + :return: + """ + data_json = json.dumps(payment_type) + self.parameters['paymentType'] = data_json + url = self.apiUrl + 'reference/payment-types/' + payment_type['code'] + '/edit' + + return self.make_request(url, 'POST') + + def payment_statuses(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/payment-statuses' + + return self.make_request(url) + + def payment_statuses_edit(self, payment_status): + """ + + :param payment_status: + :return: + """ + data_json = json.dumps(payment_status) + self.parameters['paymentStatus'] = data_json + url = self.apiUrl + 'reference/payment-statuses/' + payment_status['code'] + '/edit' + + return self.make_request(url, 'POST') + + def product_statuses(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/product-statuses' + + return self.make_request(url) + + def product_statuses_edit(self, product_status): + """ + + :param product_status: + :return: + """ + data_json = json.dumps(product_status) + self.parameters['productStatus'] = data_json + url = self.apiUrl + 'reference/product-statuses/' + product_status['code'] + '/edit' + + return self.make_request(url, 'POST') + + def order_types(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/order-types' + + return self.make_request(url) + + def order_types_edit(self, order_type): + """ + + :param order_type: + :return: + """ + data_json = json.dumps(order_type) + self.parameters['orderType'] = data_json + url = self.apiUrl + 'reference/order-types/' + order_type['code'] + '/edit' + + return self.make_request(url, 'POST') + + def order_methods(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/order-methods' + + return self.make_request(url) + + def order_methods_edit(self, order_method): + """ + + :param order_method: + :return: + """ + data_json = json.dumps(order_method) + self.parameters['orderMethod'] = data_json + url = self.apiUrl + 'reference/order-methods/' + order_method['code'] + '/edit' + + return self.make_request(url, 'POST') + + def status_groups(self): + """ + :return + """ + url = self.apiUrl + 'reference/status-groups' + + return self.make_request(url) + + def statuses(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/statuses' + + return self.make_request(url) + + def statuses_edit(self, status): + """ + + :param status: + :return: + """ + data_json = json.dumps(status) + self.parameters['status'] = data_json + url = self.apiUrl + 'reference/statuses/' + status['code'] + '/edit' + + return self.make_request(url, 'POST') + + def stores(self): + """ + + :return: + """ + url = self.apiUrl + 'reference/stores' + + return self.make_request(url) + + def stores_edit(self, store): + """ + + :param store: + :return: + """ + data_json = json.dumps(store) + self.parameters['status'] = data_json + url = self.apiUrl + 'reference/stores/' + store['code'] + '/edit' + + return self.make_request(url, 'POST') + + def statistic_update(self): + """ + :return + """ + url = self.apiUrl + 'statistic/update' + + return self.make_request(url) + + def telephony_call_event(self, phone, call_type, code, status): + """ + + :param phone: + :param call_type: + :param code: + :param status: + :return: + """ + self.parameters['hangupStatus'] = status + self.parameters['phone'] = phone + self.parameters['code'] = code + self.parameters['type'] = call_type + url = self.apiUrl + 'telephony/call/event' + + return self.make_request(url, 'POST') + + def telephony_calls_upload(self, calls): + """ + + :param calls: + :return: + """ + data_json = json.dumps(calls) + self.parameters['calls'] = data_json + url = self.apiUrl + 'telephony/calls/upload' + + return self.make_request(url, 'POST') + + def telephony_settings(self, code, client_id, make_call_url, active, name, image): + """ + + :param code: + :param client_id: + :param make_call_url: + :param active: + :param name: + :param image: + :return: + """ + self.parameters['code'] = code + self.parameters['clientId'] = client_id + self.parameters['makeCallUrl'] = make_call_url + self.parameters['active'] = active + self.parameters['name'] = name + self.parameters['image'] = image + url = self.apiUrl + 'telephony/settings/' + str(code) + + return self.make_request(url, 'POST') + + def telephony_manager(self, phone, details=True): + """ + + :param phone: + :param details: + :return: + """ + self.parameters['phone'] = phone + self.parameters['details'] = details + url = self.apiUrl + 'telephony/manager' + + return self.make_request(url) diff --git a/retailcrm/response.py b/retailcrm/response.py new file mode 100644 index 0000000..8ca3e35 --- /dev/null +++ b/retailcrm/response.py @@ -0,0 +1,29 @@ +# coding=utf-8 + + +class Response(object): + """ + API response class + """ + + def __init__(self, code, body): + self.response_body = body + self.status_code = code + + def get_status_code(self): + """ + :return: integer + """ + return self.status_code + + def get_response(self): + """ + :return: dict + """ + return self.response_body + + def is_successfull(self): + """ + :return: boolean + """ + return int(self.status_code) < 400 diff --git a/retailcrm/version.py b/retailcrm/version.py deleted file mode 100644 index 1f88732..0000000 --- a/retailcrm/version.py +++ /dev/null @@ -1,2 +0,0 @@ -version_info = (3, 0, 3) -__version__ = "." . join(map(str, version_info)) diff --git a/setup.py b/setup.py index fb05f73..61990d0 100644 --- a/setup.py +++ b/setup.py @@ -1,20 +1,16 @@ -from os.path import join, dirname +# coding=utf-8 from setuptools import setup -from imp import load_source - -description = "RetailCrm REST API client" -version = load_source("version", join("retailcrm", "version.py")) setup( - name='api-client-python', - version=version.__version__, + name='retailcrm', + version='3.0.5', + description='Client for retailCRM API', url='https://github.com/retailcrm/api-client-python', - description=description, - long_description=open(join(dirname(__file__), 'README.md')).read(), + author='retailCRM', + author_email='integration@retailcrm.ru', keywords='crm, saas, rest, e-commerce', license='MIT', - author='RetailCrm', - author_email='integration@retailcrm.ru', + packages=['retailcrm'], package_data={}, install_requires=['requests'] ) diff --git a/test.py b/test.py deleted file mode 100644 index 95d283e..0000000 --- a/test.py +++ /dev/null @@ -1,23 +0,0 @@ -import os -import sys -import inspect -import json - -cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0])) -if cmd_folder not in sys.path: sys.path.insert(0, cmd_folder) - -cmd_subfolder = os.path.realpath( - os.path.abspath(os.path.join(os.path.split(inspect.getfile(inspect.currentframe()))[0], "subfolder"))) -if cmd_subfolder not in sys.path: - sys.path.insert(0, cmd_subfolder) - -from retailcrm import Client - -url = 'https://crm_name.retailcrm.ru' -key = 'api_key' - -crm = Client(url, key) - -result = crm.deliveryServicesList() - -print json.dumps(result)