def __call__(self, value): if value is None: return value if self.strip_nondigits: value = re.compile(r'[^\d]+').sub('', value) if not ean.is_valid(value): raise ValidationError(self.message, code='invalid')
def show_one_barcode(_barcode): """ display barcode, if two parts display separated. """ # remove space and hyphens try: barcode = str(_barcode).replace('-', '').replace(' ', '') int(barcode) except ValueError: return _barcode if len(barcode) > 16: # if extra 5 digits remove them (EAN 5) first = barcode[:-5] if stdean.is_valid(first): return '%s %s' % (first, barcode[-5:]) elif len(barcode) > 13: # if extra 2 digits remove them (EAN 2) first = barcode[:-2] if stdean.is_valid(first): return '%s %s' % (first, barcode[-2:]) return barcode
def validate_barcode(self): from stdnum import ean if len(self.barcodes) > 0: for item_barcode in self.barcodes: options = frappe.get_meta("Item Barcode").get_options("barcode_type").split('\n') if item_barcode.barcode: duplicate = frappe.db.sql( """select parent from `tabItem Barcode` where barcode = %s and parent != %s""", (item_barcode.barcode, self.name)) if duplicate: frappe.throw(_("Barcode {0} already used in Item {1}").format( item_barcode.barcode, duplicate[0][0]), frappe.DuplicateEntryError) item_barcode.barcode_type = "" if item_barcode.barcode_type not in options else item_barcode.barcode_type if item_barcode.barcode_type and item_barcode.barcode_type.upper() in ('EAN', 'UPC-A', 'EAN-13', 'EAN-8'): if not ean.is_valid(item_barcode.barcode): frappe.throw(_("Barcode {0} is not a valid {1} code").format( item_barcode.barcode, item_barcode.barcode_type), InvalidBarcode)
def valid_barcode(barcode): ''' validates a barcode with stdnum ''' # remove space and hyphens try: barcode = str(barcode).replace('-', '').replace(' ', '') int(barcode) except ValueError: return False if len(barcode) > 16: # if extra 5 digits remove them (EAN 5) barcode = barcode[:-5] elif len(barcode) > 13: # if extra 2 digits remove them (EAN 2) barcode = barcode[:-2] return stdean.is_valid(barcode)
def ean(candidate): """ Checks a candidate number for validity according to the EAN checksum calculation. Note that this validator does not enforce any length checks (usually 13 or 8). http://en.wikipedia.org/wiki/International_Article_Number_(EAN) .. deprecated:: 2.2 Use the ean function in the python-stdnum_ library instead. .. _python-stdnum: https://arthurdejong.org/python-stdnum/ """ warnings.warn( 'ean is deprecated in favor of the ean function in the python-stdnum library.', RemovedInLocalflavor30Warning, ) if not isinstance(candidate, str): candidate = str(candidate) return stdnum_ean.is_valid(candidate)
def validate_barcode(self): from stdnum import ean if len(self.barcodes) > 0: for item_barcode in self.barcodes: options = frappe.get_meta("Item Barcode").get_options("barcode_type").split('\n') if item_barcode.barcode: duplicate = frappe.db.sql( """select parent from `tabItem Barcode` where barcode = %s and parent != %s""", (item_barcode.barcode, self.name)) if duplicate: frappe.throw(_("Barcode {0} already used in Item {1}").format( item_barcode.barcode, duplicate[0][0])) item_barcode.barcode_type = "" if item_barcode.barcode_type not in options else item_barcode.barcode_type if item_barcode.barcode_type and item_barcode.barcode_type.upper() in ('EAN', 'UPC-A', 'EAN-13', 'EAN-8'): if not ean.is_valid(item_barcode.barcode): frappe.throw(_("Barcode {0} is not a valid {1} code").format( item_barcode.barcode, item_barcode.barcode_type), InvalidBarcode) if item_barcode.barcode != item_barcode.name: # if barcode is getting updated , the row name has to reset. # Delete previous old row doc and re-enter row as if new to reset name in db. item_barcode.set("__islocal", True) item_barcode.name = None frappe.delete_doc("Item Barcode", item_barcode.name)
def provider_search(request, *args, **kwargs): item_type = kwargs.get('item_type', None) item_id = kwargs.get('item_id', None) provider = kwargs.get('provider', None) query = kwargs.get('query', None) #log.debug('query: %s' % (query)) results = [] error = None if provider == 'discogs': #query = re.sub('[^A-Za-z0-9 :]+', '', query) query = query.replace('(', '') query = query.replace(')', '') results = discogs_ordered_search(query, item_type) query = query.replace('"', '"') if provider == 'musicbrainz': _type = item_type if item_type == 'media': _type = 'recording' if ean.is_valid(query): log.debug('ean barcode detected. switching url composition') t_query = query.replace('-', '') url = 'http://%s/ws/2/%s?query=barcode:%s&fmt=json' % ( MUSICBRAINZ_HOST, _type, t_query) else: #query = re.sub('[^A-Za-z0-9 :]+', '', query) t_query = asciiDammit(query) """ escape lucene special characters: https://lucene.apache.org/core/4_3_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description """ t_query = t_query\ .replace('!', '\!')\ .replace('+', '\+')\ .replace('-', '\-')\ .replace('~', '\~')\ .replace('*', '\*')\ .replace('?', '\?')\ .replace('"', '\\"')\ .replace('/', '\/')\ .replace('(', '\(')\ .replace(')', '\)')\ .replace('[', '\[')\ .replace(']', '\]')\ .replace(':', '\:')\ .replace('artist\:', 'artist:') t_query = urllib.quote(t_query) url = 'http://%s/ws/2/%s?query=%s&fmt=json' % (MUSICBRAINZ_HOST, _type, t_query) query = urllib.unquote(t_query) query = query\ .replace('\!', '!')\ .replace('\+', '+')\ .replace('\-', '-')\ .replace('\~', '~')\ .replace('\*', '*')\ .replace('\?', '?')\ .replace('\\"', "")\ .replace('\/', '/')\ .replace('\(', '(')\ .replace('\)', ')')\ .replace('\[', '[')\ .replace('\]', ']')\ .replace('\:', ':') log.debug('query url: %s' % (url)) r = requests.get(url) if item_type == 'release': results = json.loads(r.text)['releases'] for result in results: result[ 'uri'] = 'http://musicbrainz.org/release/%s' % result['id'] result['thumb'] = 'http://coverartarchive.org/%s/%s' % ( item_type, result['id']) if item_type == 'artist': results = json.loads(r.text)['artists'] for result in results: result[ 'uri'] = 'http://musicbrainz.org/artist/%s' % result['id'] result['thumb'] = 'http://coverartarchive.org/%s/%s' % ( item_type, result['id']) if item_type == 'label': results = json.loads(r.text)['labels'] for result in results: result[ 'uri'] = 'http://musicbrainz.org/label/%s' % result['id'] result['thumb'] = 'http://coverartarchive.org/%s/%s' % ( item_type, result['id']) if item_type == 'media': results = json.loads(r.text)['recordings'] for result in results: result['uri'] = 'http://musicbrainz.org/recording/%s' % result[ 'id'] return json.dumps({ 'query': query, 'results': results, 'error': error, })
def check_code_gtin14(number): ''' Check gtin14 code. ''' return ean.is_valid(number) and len(number) == 14
def check_code_ean8(number): ''' Check ean8 code. ''' return ean.is_valid(number) and len(number) == 8
def check_code_upc(number): ''' Check upc code. ''' return ean.is_valid(number) and len(number) == 12
def run(self): self.ensure_one() ean = self.ean.strip() if len(ean) != 13: raise UserError( _("The barcode must have 13 digits (it has %d digits).") % len(ean)) if not is_valid(ean): raise UserError( _("The barcode %s is not a valid EAN-13 barcode.") % ean) ppo = self.env['product.product'] action = self.env.ref( 'product.product_template_action_all').sudo().read()[0] action['view_mode'] = 'form,tree,kanban' action['views'] = False existing_product = ppo.with_context(active_test=False).search( [('barcode', '=', ean)], limit=1) if existing_product: action['res_id'] = existing_product.id # TODO add warning return action apikey = tools.config.get('chasseauxlivres_apikey', False) if not apikey: raise UserError( _("API Key of chasse-aux-livres.fr missing in the Odoo server config file." )) url = "https://www.chasse-aux-livres.fr/api/v1/item?key=%s&ids=%s" % ( apikey, ean) try: res = requests.get(url) if res.status_code not in (200, 201): raise UserError( _("The webservice of chasse-aux-livres.fr returned an HTTP error code %s." ) % res.status_code) res_dict = res.json() except Exception as e: raise UserError( _("Error in the webservice call to chasse-aux-livres.fr. Technical error details: %s." ) % e) logger.info('The webservice of chasse-aux-livres.fr returned %s', res_dict) if not res_dict.get("results"): raise UserError( _("The answer of the chasse-aux-livres.fr webservice is invalid (missing 'results' key)." )) if not res_dict['results'].get(ean): raise UserError(_("TODO")) if not isinstance(res_dict['results'][ean], list): raise if len(res_dict['results'][ean]) <= 0: raise res_book = res_dict['results'][ean][0] name = res_book.get('title') list_price = 0 if res_book.get('listPrice'): try: list_price = round(res_book.get('listPrice') / 100, 2) except Exception: raise UserError( _("Error when converting price (%s).") % res_book.get('listPrice')) author = res_book.get('authors') if isinstance(author, list): author = ', '.join(author) if author and author.lower() == 'nc': author = False image_url = res_book.get('image') logger.info('Image URL = %s', image_url) image_1920 = False if image_url: try: image_res = requests.get(image_url) if image_res.status_code in (200, 201): image_1920 = base64.encodebytes(image_res.content) except Exception as e: logger.warning('Failed to download image. Error: %s', e) manufacturer_id = False if res_book.get('editor') and len(res_book['editor']) > 2: editor = res_book['editor'].strip() partner_editor = self.env['res.partner'].search( [('name', 'ilike', editor), ('is_company', '=', True)], limit=1) if partner_editor: manufacturer_id = partner_editor.id weight = 0 if res_book.get('weight'): try: weight = round( res_book['weight'] / 1000, self.env['decimal.precision'].precision_get( 'Stock Weight')) except Exception: logger.warning('Could not convert weight %s', res_book['weight']) context = { 'default_name': name, 'default_type': 'product', 'default_author': author, 'default_barcode': ean, 'default_list_price': list_price, 'default_image_1920': image_1920, 'default_manufacturer_id': manufacturer_id, 'default_weight': weight, # 'default_collection': res_book.get('collection'), } action['context'] = context # TODO return action