def get(self, model=None, id=None, **payload): ioc_name = model model = request.env[self._model].sudo().search([("model", "=", model)], limit=1) if model: domain, fields, offset, limit, order = extract_arguments(payload) data = (request.env[model.model].sudo().search_read( domain=domain, fields=fields, offset=offset, limit=limit, order=order, )) if id: domain = [("id", "=", int(id))] data = (request.env[model.model].sudo().search_read( domain=domain, fields=fields, offset=offset, limit=limit, order=order, )) if data: return valid_response(data) else: return valid_response(data) return invalid_response( "invalid object model", "The model %s is not available in the registry." % ioc_name, )
def post(self, model=None, id=None, **payload): """Create a new record. Basic sage: import requests headers = { 'content-type': 'application/x-www-form-urlencoded', 'charset': 'utf-8', 'access-token': 'access_token' } data = { 'name': 'Babatope Ajepe', 'country_id': 105, 'child_ids': [ { 'name': 'Contact', 'type': 'contact' }, { 'name': 'Invoice', 'type': 'invoice' } ], 'category_id': [{'id': 9}, {'id': 10}] } req = requests.post('%s/api/res.partner/' % base_url, headers=headers, data=data) """ import ast payload = payload.get("payload", {}) ioc_name = model model = request.env[self._model].search([("model", "=", model)], limit=1) values = {} if model: try: # changing IDs from string to int. for k, v in payload.items(): if "__api__" in k: values[k[7:]] = ast.literal_eval(v) else: values[k] = v resource = request.env[model.model].create(values) except Exception as e: request.env.cr.rollback() return invalid_response("params", e) else: data = resource.read() if resource: return valid_response(data) else: return valid_response(data) return invalid_response( "invalid object model", "The model %s is not available in the registry." % ioc_name, )
def get(self, model=None, id=None, **payload): print(payload) try: ioc_name = model model = request.env[self._model].search([("model", "=", model)], limit=1) if model: # domain, fields, offset, limit, order = extract_arguments(payload) domain = payload.get('domain') fields = payload.get('fields') if fields: fields = str(fields).split(',') # id,name offset = payload.get('offset') # '5' if offset: offset = int(offset) limit = payload.get('limit') if limit: limit = int(limit) order = payload.get('order') data = request.env[model.model].search_read( domain=domain, fields=fields, offset=offset, limit=limit, order=order, ) print(domain, fields, offset, limit, order) if id: domain = [("id", "=", int(id))] data = request.env[model.model].search_read( domain=domain, fields=fields, offset=offset, limit=limit, order=order, ) if data: return valid_response(data) else: return valid_response(data) return invalid_response( "invalid object model", "The model %s is not available in the registry." % ioc_name, ) except AccessError as e: return invalid_response("Access error", "Error: %s" % e.name)
def patch(self, model=None, id=None, action=None, **payload): """.""" try: _id = int(id) except Exception as e: return invalid_response( "invalid object id", "invalid literal %s for id with base " % id) try: record = request.env[model].sudo().search([("id", "=", _id)]) _callable = action in [ method for method in dir(record) if callable(getattr(record, method)) ] if record and _callable: # action is a dynamic variable. getattr(record, action)() else: return invalid_response( "missing_record", "record object with id %s could not be found or %s object has no method %s" % (_id, model, action), 404, ) except Exception as e: return invalid_response("exception", e, 503) else: return valid_response("record %s has been successfully patched" % record.id)
def patch(self, model=None, id=None, action=None, **payload): """.""" payload = payload.get('payload') action = action if action else payload.get('_method') args = [] # args = re.search('\((.+)\)', action) # if args: # args = ast.literal_eval(args.group()) # if re.search('\w.+\(', action): # action = re.search('\w.+\(', action) # action = action.group()[0:-1] try: _id = int(id) except Exception as e: return invalid_response("invalid object id", "invalid literal %s for id with base" % id) try: record = request.env[model].sudo().search([("id", "=", _id)]) _callable = action in [method for method in dir(record) if callable(getattr(record, method))] if record and _callable: # action is a dynamic variable. getattr(record, action)(*args) if args else getattr(record, action)() else: return invalid_response( "missing_record", "record object with id %s could not be found or %s object has no method %s" % (_id, model, action), 404, ) except Exception as e: return invalid_response("exception", e, 503) else: return valid_response("record %s has been successfully update" % record.id)
def put(self, model=None, id=None, **payload): """.""" values = {} payload = request.httprequest.data.decode() payload = json.loads(payload) try: _id = int(id) except Exception as e: return invalid_response("invalid object id", "invalid literal %s for id with base " % id) _model = request.env[self._model].sudo().search([("model", "=", model)], limit=1) if not _model: return invalid_response( "invalid object model", "The model %s is not available in the registry." % model, 404, ) try: record = request.env[_model.model].sudo().browse(_id) for k, v in payload.items(): if "__api__" in k: values[k[7:]] = ast.literal_eval(v) else: values[k] = v record.write(values) except Exception as e: request.env.cr.rollback() return invalid_response("exception", e) else: return valid_response(record.read())
def put(self, model=None, id=None, **payload): """.""" payload = payload.get('payload', {}) try: _id = int(id) except Exception as e: return invalid_response( "invalid object id", "invalid literal %s for id with base " % id) _model = request.env[self._model].sudo().search( [("model", "=", model)], limit=1) if not _model: return invalid_response( "invalid object model", "The model %s is not available in the registry." % model, 404, ) try: record = request.env[_model.model].sudo().browse(_id) record.write(payload) except Exception as e: request.env.cr.rollback() return invalid_response("exception", e.name) else: return valid_response(record.read())
def post(self, model=None, id=None, **payload): """Create a new record. Basic sage: import requests headers = { 'content-type': 'application/x-www-form-urlencoded', 'charset': 'utf-8', 'access-token': 'access_token' } data = { 'name': 'Babatope Ajepe', 'country_id': 105, 'child_ids': [ { 'name': 'Contact', 'type': 'contact' }, { 'name': 'Invoice', 'type': 'invoice' } ], 'category_id': [{'id': 9}, {'id': 10}] } req = requests.post('%s/api/res.partner/' % base_url, headers=headers, data=data) """ ioc_name = model model = request.env[self._model].sudo().search([("model", "=", model)], limit=1) if model: try: resource = request.env[model.model].sudo().create(payload) except Exception as e: return invalid_response("params", e) else: data = {"id": resource.id} if resource: return valid_response(data) else: return valid_response(data) return invalid_response( "invalid object model", "The model %s is not available in the registry." % ioc_name, )
def get(self, model=None, id=None, **payload): ioc_name = model model = request.env[self._model].sudo().search([('model', '=', model)], limit=1) if model: domain, fields, offset, limit, order = extract_arguments(payload) data = request.env[model.model].sudo().search_read(domain=domain, fields=fields, offset=offset, limit=limit, order=order) if data: return valid_response(data) else: return valid_response(data) return invalid_response( 'invalid object model', 'The model %s is not available in the registry.' % ioc_name)
def delete(self, **post): """.""" _token = request.env["api.access.token"] access_token = request.httprequest.headers.get("access_token") access_token = _token.search([("token", "=", access_token)]) if not access_token: info = "No access token was provided in request!" error = "No Access Token" _logger.error(info) return invalid_response(error, info) return valid_response(access_token.unlink())
def category_products(self, **payload): data = request.env['product.template'].sudo().search_read( domain=[('public_categ_ids', 'in', [payload.get('category_id')])], fields=['id', 'name', 'description', 'price', 'public_categ_ids'], offset=None, limit=None, order=None ) if data: return valid_response(data) else: return invalid_response(data)
def stock(self, **payload): product = request.env['product.product'].sudo().browse(int(payload.get('product_id'))) available_qty = product.qty_available # For specific warehouse / location: #available_qty = product.with_context({'warehouse': WAREHOUSE_ID}).qty_available #available_qty = product.with_context({'location': LOCATION_ID}).qty_available # Source: https://www.odoo.com/es_ES/forum/ayuda-1/question/how-to-get-product-quantity-109870 return valid_response({ 'stock': available_qty })
def delete(self, **post): """.""" _token = request.env['api.access_token'] access_token = request.httprequest.headers.get('access_token') access_token = _token.search([('token', '=', access_token)]) if not access_token: info = "No access token was provided in request!" error = 'no_access_token' _logger.error(info) return invalid_response(error, info, 400) for token in access_token: token.unlink() # Successful response: return valid_response({ "desc": 'token successfully deleted', "delete": True })
def delete(self, **post): """.""" _token = request.env["api.access_token"] access_token = request.httprequest.headers.get("access_token") access_token = _token.search([("token", "=", access_token)]) if not access_token: info = "No access token was provided in request!" error = "Access token is missing in the request header" _logger.error(info) return invalid_response(400, error, info) for token in access_token: token.unlink() # Successful response: return valid_response([{ "desc": "access token successfully deleted", "delete": True }])
def delete(self, model=None, id=None, **payload): """.""" try: _id = int(id) except Exception as e: return invalid_response("invalid object id", "invalid literal %s for id with base " % id) try: record = request.env[model].sudo().search([("id", "=", _id)]) if record: record.unlink() else: return invalid_response("missing_record", "record object with id %s could not be found" % _id, 404,) except Exception as e: request.env.cr.rollback() return invalid_response("exception", e.name, 503) else: return valid_response("record %s has been successfully deleted" % record.id)
def put(self, model=None, id=None, **payload): """.""" try: _id = int(id) except Exception as e: return invalid_response( 'invalid object id', 'invalid literal %s for id with base ' % id) _model = request.env[self._model].sudo().search( [('model', '=', model)], limit=1) if not _model: return invalid_response( 'invalid object model', 'The model %s is not available in the registry.' % model, 404) try: request.env[_model.model].sudo().browse(_id).write(payload) except Exception as e: return invalid_response('exception', e.name) else: return valid_response('update %s record with id %s successfully!' % (_model.model, _id))
def delete(self, model=None, id=None, **payload): """.""" try: _id = int(id) except Exception as e: return invalid_response( 'invalid object id', 'invalid literal %s for id with base ' % id) try: record = request.env[model].sudo().search([('id', '=', _id)]) if record: record.unlink() else: return invalid_response( 'missing_record', 'record object with id %s could not be found' % _id, 404) except Exception as e: return invalid_response('exception', e.name, 503) else: return valid_response('record %s has been successfully deleted' % record.id)
def put(self, model=None, id=None, **payload): """.""" try: _id = int(id) except Exception as e: return invalid_response( "invalid object id", "invalid literal %s for id with base " % id) _model = (request.env[self._model].sudo().search( [("model", "=", model)], limit=1)) if not _model: return invalid_response( "invalid object model", "The model %s is not available in the registry." % model, 404, ) try: request.env[_model.model].sudo().browse(_id).write(payload) except Exception as e: return invalid_response("exception", e.name) else: return valid_response("update %s record with id %s successfully!" % (_model.model, _id))
def patch(self, model=None, id=None, action=None, **payload): """.""" args = [] try: _id = int(id) except Exception as e: return invalid_response("invalid object id", "invalid literal %s for id with base" % id) try: record = request.env[model].sudo().search([("id", "=", _id)], limit=1) _callable = action in [method for method in dir(record) if callable(getattr(record, method))] if record and _callable: # action is a dynamic variable. getattr(record, action)(*args) if args else getattr(record, action)() else: return invalid_response( "invalid object or method", "The given action '%s ' cannot be performed on record with id '%s' because '%s' has no such method" % (action, _id, model), 404, ) except Exception as e: return invalid_response("exception", e, 503) else: return valid_response("record %s has been successfully update" % record.id)
def categories(self, **payload): #str(json.loads(payload.get('request')).get('_appliedFilters')[0].get('value').get('eq')) # == 2 --> root categories applied_filter = json.loads(payload.get('request')).get('_appliedFilters')[0] if applied_filter.get('attribute') == "url_key": parent_id = 2 else: parent_id = applied_filter.get('value').get('eq') if parent_id == 2: # Root categories categories = request.env['product.public.category'].sudo().search_read( domain=[('parent_id', '=', False)], fields=['id', 'name', 'display_name', 'parent_id', 'child_id'], offset=None, limit=None, order=None) if categories: response = self.categories_to_response(categories, 2, parent_id) return simple_response(response) else: return invalid_response({ "error": 500 }) else: categories = request.env['product.public.category'].sudo().search_read( domain=[('parent_id', '=', parent_id - self.category_offset)], fields=['id', 'name', 'display_name', 'parent_id', 'child_id'], offset=None, limit=None, order=None) if categories: response = self.categories_to_response(categories, 3, parent_id) return simple_response(response) else: return invalid_response({ "error": 500 }) response = { "took":1, "timed_out": False, "_shards":{ "total":5, "successful":5, "skipped":0, "failed":0 }, "hits":{ "total":2, "max_score": None, "hits":[ { "_index":"vue_storefront_catalog_1552559102", "_type":"category", "_id":"21", "_score": None, "_source":{ "path":"1/2/20/21", "is_active": True, "level":3, "product_count":0, "children_count":"4", "parent_id": parent_id, "name":"Tops" + str(json.loads(payload.get('request')).get('_appliedFilters')[0].get('value').get('eq')), "id":21, "url_path":"women/tops-women/tops-21", "url_key":"tops-21", "children_data":[ { "id":23 }, { "id":24 }, { "id":25 }, { "id":26 } ] }, "sort":[ 1 ] }, { "_index":"vue_storefront_catalog_1552559102", "_type":"category", "_id":"22", "_score": None, "_source":{ "path":"1/2/20/22", "is_active": True, "level":3, "product_count":0, "children_count":"2", "parent_id": parent_id, "name":"Bottoms", "id":22, "url_key":"bottoms-22", "children_data":[ { "id":27 }, { "id":28 } ], "url_path":"women/bottoms-women/bottoms-22" }, "sort":[ 2 ] } ] } } return simple_response(response) response = { "items": [ { "id": 27, "parent_id": 2, "name": "Category without childs", "is_active": True, "position": 5, "level": 2, "product_count": 2, "entity_type_id": 3, "attribute_set_id": 3, "children_count": 0, "request_path": "accessories/shoes.html", "children_data": [ ], "created_at": "2017-11-06 12:16:41", "updated_at": "2017-11-06 12:16:42", "path": "1/2/29", "available_sort_by": [ ], "include_in_menu": False, "display_mode": "PAGE", "is_anchor": "0", "url_key": "promotions-29", "url_path": "promotions/promotions-29", "slug": "promotions-29", "tsk": 1551705224325 } ], "total": 3, "start": 1, "perPage": 3, "aggregations": [ ] } return simple_response(response) data = request.env['product.public.category'].sudo().search_read( domain=[('parent_id', '=', False)], fields=['id', 'name', 'display_name', 'parent_id', 'child_id'], offset=None, limit=None, order=None) if data: return valid_response(data) else: return invalid_response(data)
def attributes_json(self, **payload): attributes = [] attributes.append(self.attributeJSON("93", "color", "Color")) attributes.append(self.attributeJSON("142", "size", "Size")) return valid_response(attributes)
def products(self, **payload): # Successful response: #return werkzeug.wrappers.Response( #status=200, #content_type='application/json; charset=utf-8', #headers=[('Cache-Control', 'no-store'), # ('Pragma', 'no-cache')], #response=json.dumps({ # 'products': 'list of products', #}), #) data = request.env['product.template'].sudo().search_read( domain=[], fields=['id', 'name', 'description', 'list_price', 'public_categ_ids', 'default_code', 'attribute_line_ids'], offset=None, limit=None, order=None) if data: #return valid_response(self.productJSON()) products = [] for element in data: # Preparing data for "configurable_options" variants_array = [] attribute_line_ids = element.get('attribute_line_ids') for attribute_line_id in attribute_line_ids: variant = request.env['product.template.attribute.line'].sudo().search_read( domain=[('id', '=', attribute_line_id)], fields=['id', 'value_ids', 'attribute_id'], offset=None, limit=None, order=None)[0] value_ids = variant['value_ids'] variant['attributes'] = [] for value_id in value_ids: attribute = request.env['product.attribute.value'].sudo().search_read( domain=[('id', '=', value_id)], fields=['name', 'html_color'], offset=None, limit=None, order=None) variant['attributes'].append(attribute) variants_array.append(variant) # Preparing data for "configurable_children" # "product.attribute.value.product.product.rel" relates products with attribute values # find products for current template configurable_childrens = request.env['product.product'].sudo().search_read( domain=[('product_tmpl_id', '=', element.get('id'))], fields=['id', 'attribute_value_ids'], offset=None, limit=None, order=None) configurable_children_array = [] for configurable_children in configurable_childrens: configurable_children['list_price'] = element.get('list_price') configurable_children['attributes'] = [] value_ids = configurable_children['attribute_value_ids'] for value_id in value_ids: attribute = request.env['product.attribute.value'].sudo().search_read( domain=[('id', '=', value_id)], fields=['id', 'name', 'attribute_id'], offset=None, limit=None, order=None) configurable_children['attributes'].append(attribute) configurable_children_array.append( configurable_children ) products.append(self.productJSON( element.get('name'), element.get('id'), element.get('default_code'), element.get('list_price'), element.get('attribute_line_ids'), variants_array, configurable_children_array, )) return valid_response(products) else: return invalid_response(data)
def http_options(self, model=None, id=None, **payload): return valid_response({}, http_method=HTTP_METHOD_OPTION)
def token(self, **post): """The token URL to be used for getting the access_token: Args: **post must contain login and password. Returns: returns https response code 404 if failed error message in the body in json format and status code 202 if successful with the access_token. Example: import requests headers = {'content-type': 'text/plain', 'charset':'utf-8'} data = { 'login': '******', 'password': '******', 'db': 'galago.ng' } base_url = 'http://odoo.ng' eq = requests.post( '{}/api/auth/token'.format(base_url), data=data, headers=headers) content = json.loads(req.content.decode('utf-8')) headers.update(access-token=content.get('access_token')) """ _token = request.env["api.access.token"] params = ["db", "login", "password"] params = {key: post.get(key) for key in params if post.get(key)} db_name = tools.config.get('db_name') db, username, password = ( params.get("db") or db_name, post.get("login"), post.get("password"), ) _credentials_includes_in_body = all([db, username, password]) if not _credentials_includes_in_body: # The request post body is empty the credetials maybe passed via the headers. headers = request.httprequest.headers db = headers.get("db") or db_name username = headers.get("login") password = headers.get("password") _credentials_includes_in_headers = all([db, username, password]) if not _credentials_includes_in_headers: # Empty 'db' or 'username' or 'password: return invalid_response( "Missing error", "Either of the following are missing [username,password]", 403, ) # Login in odoo database: try: request.session.authenticate(db, username, password) except Exception as e: # Invalid database: info = "The database name is not valid {}".format((e)) error = "invalid_database" _logger.error(info) return invalid_response(error, info, 400) uid = request.session.uid # odoo login failed: if not uid: info = "Authentication failed" error = "Authentication failed" _logger.error(info) return invalid_response(error, info, 401) # Generate tokens access_token = _token.find_one_or_create_token(user_id=uid, create=True) # Successful response: return valid_response( { "uid": uid, "access_token": access_token, }, status=200, )