def _read_xls_book(self, book): sheet = book.sheet_by_index(0) # emulate Sheet.get_rows for pre-0.9.4 for row in pycompat.imap(sheet.row, range(sheet.nrows)): values = [] for cell in row: if cell.ctype is xlrd.XL_CELL_NUMBER: is_float = cell.value % 1 != 0.0 values.append( pycompat.text_type(cell.value) if is_float else pycompat.text_type(int(cell.value)) ) elif cell.ctype is xlrd.XL_CELL_DATE: is_datetime = cell.value % 1 != 0.0 # emulate xldate_as_datetime for pre-0.9.3 dt = datetime.datetime(*xlrd.xldate.xldate_as_tuple(cell.value, book.datemode)) values.append( dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT) if is_datetime else dt.strftime(DEFAULT_SERVER_DATE_FORMAT) ) elif cell.ctype is xlrd.XL_CELL_BOOLEAN: values.append(u'True' if cell.value else u'False') elif cell.ctype is xlrd.XL_CELL_ERROR: raise ValueError( _("Error cell found while reading XLS/XLSX file: %s") % xlrd.error_text_from_code.get( cell.value, "unknown error code %s" % cell.value) ) else: values.append(cell.value) if any(x for x in values if x.strip()): yield values
def _convert_import_data(self, fields, options): """ Extracts the input BaseModel and fields list (with ``False``-y placeholders for fields to *not* import) into a format Model.import_data can use: a fields list without holes and the precisely matching data matrix :param list(str|bool): fields :returns: (data, fields) :rtype: (list(list(str)), list(str)) :raises ValueError: in case the import data could not be converted """ # Get indices for non-empty fields indices = [index for index, field in enumerate(fields) if field] if not indices: raise ValueError(_("You must configure at least one field to import")) # If only one index, itemgetter will return an atom rather # than a 1-tuple if len(indices) == 1: mapper = lambda row: [row[indices[0]]] else: mapper = operator.itemgetter(*indices) # Get only list of actually imported fields import_fields = [f for f in fields if f] rows_to_import = self._read_file(options) if options.get('headers'): rows_to_import = itertools.islice(rows_to_import, 1, None) data = [ list(row) for row in pycompat.imap(mapper, rows_to_import) # don't try inserting completely empty rows (e.g. from # filtering out o2m fields) if any(row) ] return data, import_fields
def record_to_html(self, record, field_name, options): assert options['tagName'] != 'img',\ "Oddly enough, the root tag of an image field can not be img. " \ "That is because the image goes into the tag, or it gets the " \ "hose again." if options.get('qweb_img_raw_data', False): return super(Image, self).record_to_html(record, field_name, options) aclasses = ['img', 'img-fluid'] if options.get('qweb_img_responsive', True) else ['img'] aclasses += options.get('class', '').split() classes = ' '.join(pycompat.imap(escape, aclasses)) max_size = None if options.get('resize'): max_size = options.get('resize') else: max_width, max_height = options.get('max_width', 0), options.get('max_height', 0) if max_width or max_height: max_size = '%sx%s' % (max_width, max_height) sha = hashlib.sha1(str(getattr(record, '__last_update')).encode('utf-8')).hexdigest()[0:7] max_size = '' if max_size is None else '/%s' % max_size avoid_if_small = '&avoid_if_small=true' if options.get('avoid_if_small') else '' src = '/web/image/%s/%s/%s%s?unique=%s%s' % (record._name, record.id, field_name, max_size, sha, avoid_if_small) alt = None if options.get('alt-field') and getattr(record, options['alt-field'], None): alt = escape(record[options['alt-field']]) elif options.get('alt'): alt = options['alt'] src_zoom = None if options.get('zoom') and getattr(record, options['zoom'], None): src_zoom = '/web/image/%s/%s/%s%s?unique=%s' % (record._name, record.id, options['zoom'], max_size, sha) elif options.get('zoom'): src_zoom = options['zoom'] atts = OrderedDict() atts["src"] = src atts["class"] = classes atts["style"] = options.get('style') atts["alt"] = alt atts["data-zoom"] = src_zoom and u'1' or None atts["data-zoom-image"] = src_zoom atts["data-no-post-process"] = options.get('data-no-post-process') atts = self.env['ir.qweb']._post_processing_att('img', atts, options.get('template_options')) img = ['<img'] for name, value in atts.items(): if value: img.append(' ') img.append(escape(pycompat.to_text(name))) img.append('="') img.append(escape(pycompat.to_text(value))) img.append('"') img.append('/>') return u''.join(img)
def fiscal_pos_map_to_csv(self): writer = csv.writer(open('account.fiscal.' 'position.tax.template-%s.csv' % self.suffix, 'wb')) fiscal_pos_map_iterator = self.iter_fiscal_pos_map() keys = next(fiscal_pos_map_iterator) writer.writerow(keys) for row in fiscal_pos_map_iterator: writer.writerow(pycompat.imap(_e, pycompat.values(row)))
def taxes_to_csv(self): writer = csv.writer(open('account.tax.template-%s.csv' % self.suffix, 'wb')) taxes_iterator = self.iter_taxes() keys = next(taxes_iterator) writer.writerow(keys[3:] + ['sequence']) seq = 100 for row in sorted(taxes_iterator, key=lambda r: r['description']): if not _is_true(row['active']): continue seq += 1 if row['parent_id:id']: cur_seq = seq + 1000 else: cur_seq = seq writer.writerow(list(pycompat.imap(_e, list(pycompat.values(row))[3:])) + [cur_seq])
def record_to_html(self, record, field_name, options): assert options['tagName'] != 'img',\ "Oddly enough, the root tag of an image field can not be img. " \ "That is because the image goes into the tag, or it gets the " \ "hose again." if options.get('qweb_img_raw_data', False): return super(Image, self).record_to_html(record, field_name, options) aclasses = ['img', 'img-responsive'] if options.get('qweb_img_responsive', True) else ['img'] aclasses += options.get('class', '').split() classes = ' '.join(pycompat.imap(escape, aclasses)) max_size = None if options.get('resize'): max_size = options.get('resize') else: max_width, max_height = options.get('max_width', 0), options.get('max_height', 0) if max_width or max_height: max_size = '%sx%s' % (max_width, max_height) sha = hashlib.sha1(getattr(record, '__last_update').encode('utf-8')).hexdigest()[0:7] max_size = '' if max_size is None else '/%s' % max_size avoid_if_small = '&avoid_if_small=true' if options.get('avoid_if_small') else '' src = '/web/image/%s/%s/%s%s?unique=%s%s' % (record._name, record.id, field_name, max_size, sha, avoid_if_small) alt = None if options.get('alt-field') and getattr(record, options['alt-field'], None): alt = escape(record[options['alt-field']]) elif options.get('alt'): alt = options['alt'] src_zoom = None if options.get('zoom') and getattr(record, options['zoom'], None): src_zoom = '/web/image/%s/%s/%s%s?unique=%s' % (record._name, record.id, options['zoom'], max_size, sha) elif options.get('zoom'): src_zoom = options['zoom'] img = '<img class="%s" src="%s" style="%s"%s%s/>' % \ (classes, src, options.get('style', ''), ' alt="%s"' % alt if alt else '', ' data-zoom="1" data-zoom-image="%s"' % src_zoom if src_zoom else '') return pycompat.to_text(img)
def _convert_import_data(self, fields, options): """ Extracts the input BaseModel and fields list (with ``False``-y placeholders for fields to *not* import) into a format Model.import_data can use: a fields list without holes and the precisely matching data matrix :param list(str|bool): fields :returns: (data, fields) :rtype: (list(list(str)), list(str)) :raises ValueError: in case the import data could not be converted """ # Get indices for non-empty fields indices = [index for index, field in enumerate(fields) if field] if not indices: raise ValueError( _("You must configure at least one field to import")) # If only one index, itemgetter will return an atom rather # than a 1-tuple if len(indices) == 1: mapper = lambda row: [row[indices[0]]] else: mapper = operator.itemgetter(*indices) # Get only list of actually imported fields import_fields = [f for f in fields if f] rows_to_import = self._read_file(options) if options.get('headers'): rows_to_import = itertools.islice(rows_to_import, 1, None) data = [ list(row) for row in pycompat.imap(mapper, rows_to_import) # don't try inserting completely empty rows (e.g. from # filtering out o2m fields) if any(row) ] return data, import_fields
def record_to_html(self, record, field_name, options): assert options['tagName'] != 'img',\ "Oddly enough, the root tag of an image field can not be img. " \ "That is because the image goes into the tag, or it gets the " \ "hose again." if options.get('qweb_img_raw_data', False): return super(Image, self).record_to_html(record, field_name, options) aclasses = ['img', 'img-fluid'] if options.get('qweb_img_responsive', True) else ['img'] aclasses += options.get('class', '').split() classes = ' '.join(pycompat.imap(escape, aclasses)) max_size = None if options.get('resize'): max_size = options.get('resize') else: max_width, max_height = options.get('max_width', 0), options.get( 'max_height', 0) if max_width or max_height: max_size = '%sx%s' % (max_width, max_height) sha = hashlib.sha1( str(getattr(record, '__last_update')).encode('utf-8')).hexdigest()[0:7] max_size = '' if max_size is None else '/%s' % max_size avoid_if_small = '&avoid_if_small=true' if options.get( 'avoid_if_small') else '' src = '/web/image/%s/%s/%s%s?unique=%s%s' % ( record._name, record.id, field_name, max_size, sha, avoid_if_small) alt = None if options.get('alt-field') and getattr(record, options['alt-field'], None): alt = escape(record[options['alt-field']]) elif options.get('alt'): alt = options['alt'] src_zoom = None if options.get('zoom') and getattr(record, options['zoom'], None): src_zoom = '/web/image/%s/%s/%s%s?unique=%s' % ( record._name, record.id, options['zoom'], max_size, sha) elif options.get('zoom'): src_zoom = options['zoom'] atts = OrderedDict() atts["src"] = src atts["class"] = classes atts["style"] = options.get('style') atts["alt"] = alt atts["data-zoom"] = src_zoom and u'1' or None atts["data-zoom-image"] = src_zoom atts["data-no-post-process"] = options.get('data-no-post-process') atts = self.env['ir.qweb']._post_processing_att( 'img', atts, options.get('template_options')) img = ['<img'] for name, value in atts.items(): if value: img.append(' ') img.append(escape(pycompat.to_text(name))) img.append('="') img.append(escape(pycompat.to_text(value))) img.append('"') img.append('/>') return u''.join(img)
def tax_codes_to_csv(self): writer = csv.writer(open('account.tax.code.template-%s.csv' % self.suffix, 'wb')) tax_codes_iterator = self.iter_tax_codes keys = next(tax_codes_iterator) writer.writerow(keys) # write structure tax codes tax_codes = {} # code: id for row in tax_codes_iterator: tax_code = row['code'] if tax_code in tax_codes: raise RuntimeError('duplicate tax code %s' % tax_code) tax_codes[tax_code] = row['id'] writer.writerow(pycompat.imap(_e, pycompat.values(row))) # read taxes and add leaf tax codes new_tax_codes = {} # id: parent_code def add_new_tax_code(tax_code_id, new_name, new_parent_code): if not tax_code_id: return name, parent_code = new_tax_codes.get(tax_code_id, (None, None)) if parent_code and parent_code != new_parent_code: raise RuntimeError('tax code "%s" already exist with ' 'parent %s while trying to add it with ' 'parent %s' % (tax_code_id, parent_code, new_parent_code)) else: new_tax_codes[tax_code_id] = (new_name, new_parent_code) taxes_iterator = self.iter_taxes() next(taxes_iterator) for row in taxes_iterator: if not _is_true(row['active']): continue if row['child_depend'] and row['amount'] != 1: raise RuntimeError('amount must be one if child_depend ' 'for %s' % row['id']) # base parent base_code = row['BASE_CODE'] if not base_code or base_code == '/': base_code = 'NA' if base_code not in tax_codes: raise RuntimeError('undefined tax code %s' % base_code) if base_code != 'NA': if row['child_depend']: raise RuntimeError('base code specified ' 'with child_depend for %s' % row['id']) if not row['child_depend']: # ... in lux, we have the same code for invoice and refund if base_code != 'NA': assert row['base_code_id:id'], 'missing base_code_id for %s' % row['id'] assert row['ref_base_code_id:id'] == row['base_code_id:id'] add_new_tax_code(row['base_code_id:id'], 'Base - ' + row['name'], base_code) # tax parent tax_code = row['TAX_CODE'] if not tax_code or tax_code == '/': tax_code = 'NA' if tax_code not in tax_codes: raise RuntimeError('undefined tax code %s' % tax_code) if tax_code == 'NA': if row['amount'] and not row['child_depend']: raise RuntimeError('TAX_CODE not specified ' 'for non-zero tax %s' % row['id']) if row['tax_code_id:id']: raise RuntimeError('tax_code_id specified ' 'for tax %s' % row['id']) else: if row['child_depend']: raise RuntimeError('TAX_CODE specified ' 'with child_depend for %s' % row['id']) if not row['amount']: raise RuntimeError('TAX_CODE specified ' 'for zero tax %s' % row['id']) if not row['tax_code_id:id']: raise RuntimeError('tax_code_id not specified ' 'for tax %s' % row['id']) if not row['child_depend'] and row['amount']: # ... in lux, we have the same code for invoice and refund assert row['tax_code_id:id'], 'missing tax_code_id for %s' % row['id'] assert row['ref_tax_code_id:id'] == row['tax_code_id:id'] add_new_tax_code(row['tax_code_id:id'], 'Taxe - ' + row['name'], tax_code) for tax_code_id in sorted(new_tax_codes): name, parent_code = new_tax_codes[tax_code_id] writer.writerow((tax_code_id, 'lu_tct_m' + parent_code, tax_code_id.replace('lu_tax_code_template_', ''), '1', '', _e(name), ''))
def _groups_branding(self, specs_tree, view_id): groups_id = self.browse(view_id).groups_id if groups_id: attr_value = ','.join(pycompat.imap(str, groups_id.ids)) for node in specs_tree.iter(tag=etree.Element): node.set('studio-view-group-ids', attr_value)
def read_xls(self, map1): # import ipdb; ipdb.set_trace() file1 = base64.b64decode(self.file1) try: book = xlrd.open_workbook(file_contents=file1 or b'') except: return [] sheet = book.sheet_by_index(0) cols = [] vals = [] x = -1 for row in pycompat.imap(sheet.row, range(sheet.nrows)): x += 1 val_one = {} c = -1 for cell in row: c += 1 if x == 0: col = str(cell.value).lower() get_map = map1.get(col, '') # if type(get_map) is list: # col_to_save = get_map[0] # else: # col_to_save = get_map # cols.append(col_to_save) cols.append(get_map) else: get_map = cols[c] if not get_map: continue val = '' if cell.ctype is xlrd.XL_CELL_NUMBER: is_float = cell.value % 1 != 0.0 val = pycompat.text_type( cell.value) if is_float else pycompat.text_type( int(cell.value)) elif cell.ctype is xlrd.XL_CELL_DATE: is_datetime = cell.value % 1 != 0.0 # emulate xldate_as_datetime for pre-0.9.3 dt = datetime.datetime(*xlrd.xldate.xldate_as_tuple( cell.value, book.datemode)) val = dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT ) if is_datetime else dt.strftime( DEFAULT_SERVER_DATE_FORMAT) elif cell.ctype is xlrd.XL_CELL_BOOLEAN: val = u'True' if cell.value else u'False' elif cell.ctype is xlrd.XL_CELL_ERROR: # raise ValueError( # _("Error cell found while reading XLS/XLSX file: %s") % # xlrd.error_text_from_code.get( # cell.value, "unknown error code %s" % cell.value) # ) val = '' else: # import ipdb; ipdb.set_trace() # print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", cell) val = cell.value # val_one[field] = val value = val if type(get_map) is list: col_to_save = get_map[0] col = get_map[3] if col_to_save: val_to_save = False tipe = get_map[1] model = get_map[2] if tipe == 'many2one': model = self.env[model] rec = model.search([('name', '=', value)]) if not rec: # create first # rec = model.create({'name': value}) raise ValidationError( _('{} : "{}" is not known'.format( col, value))) val_to_save = rec.id val_one[col_to_save] = val_to_save else: col_to_save = get_map if col_to_save: val_one[col_to_save] = value if val_one: vals.append((0, 0, val_one)) return vals