This commit replaces calls to pycompat helpers that were intended for
python 2 <-> python 3 interoperability for python 3 builtins, as python
2 is no longer officially supported by Odoo.
This includes:
* calls to imap/izip/ifilter replaced by map/zip/filter
* uses of text_type replaced by str
* uses of unichr replaced by chr
* calls to implements_to_string, implements_iterator removed
* string_types and integer_types replaced by str, int respectively
* calls to to_native replaced by calls to to_text
This is done in preparation to the removal of these deprecated helpers
in the following commit.
184 lines
7.5 KiB
Python
184 lines
7.5 KiB
Python
from collections import OrderedDict
|
|
|
|
import xlrd
|
|
from odoo.tools import pycompat
|
|
|
|
def _is_true(s):
|
|
return s not in ('F', 'False', 0, '', None, False)
|
|
|
|
|
|
class LuxTaxGenerator:
|
|
|
|
def __init__(self, filename):
|
|
self.workbook = xlrd.open_workbook('tax.xls')
|
|
self.sheet_info = \
|
|
self.workbook.sheet_by_name('INFO')
|
|
self.sheet_taxes = \
|
|
self.workbook.sheet_by_name('TAXES')
|
|
self.sheet_tax_codes = \
|
|
self.workbook.sheet_by_name('TAX.CODES')
|
|
self.sheet_fiscal_pos_map = \
|
|
self.workbook.sheet_by_name('FISCAL.POSITION.MAPPINGS')
|
|
self.suffix = self.sheet_info.cell_value(4, 2)
|
|
|
|
def iter_tax_codes(self):
|
|
keys = [c.value for c in self.sheet_tax_codes.row(0)]
|
|
yield keys
|
|
for i in range(1, self.sheet_tax_codes.nrows):
|
|
row = (c.value for c in self.sheet_tax_codes.row(i))
|
|
d = OrderedDict(zip(keys, row))
|
|
d['sign'] = int(d['sign'])
|
|
d['sequence'] = int(d['sequence'])
|
|
yield d
|
|
|
|
def iter_taxes(self):
|
|
keys = [c.value for c in self.sheet_taxes.row(0)]
|
|
yield keys
|
|
for i in range(1, self.sheet_taxes.nrows):
|
|
row = (c.value for c in self.sheet_taxes.row(i))
|
|
yield OrderedDict(zip(keys, row))
|
|
|
|
def iter_fiscal_pos_map(self):
|
|
keys = [c.value for c in self.sheet_fiscal_pos_map.row(0)]
|
|
yield keys
|
|
for i in range(1, self.sheet_fiscal_pos_map.nrows):
|
|
row = (c.value for c in self.sheet_fiscal_pos_map.row(i))
|
|
yield OrderedDict(zip(keys, row))
|
|
|
|
def tax_codes_to_csv(self):
|
|
writer = pycompat.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.to_text(v) for v in row.values()])
|
|
|
|
# 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,
|
|
u'lu_tct_m' + parent_code,
|
|
tax_code_id.replace('lu_tax_code_template_', u''),
|
|
u'1',
|
|
u'',
|
|
pycompat.to_text(name),
|
|
u''
|
|
])
|
|
|
|
def taxes_to_csv(self):
|
|
writer = pycompat.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([
|
|
pycompat.to_text(v)
|
|
for v in list(row.values())[3:]
|
|
] + [cur_seq])
|
|
|
|
def fiscal_pos_map_to_csv(self):
|
|
writer = pycompat.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.to_text(s) for s in row.values()])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
o = LuxTaxGenerator('tax.xls')
|
|
o.tax_codes_to_csv()
|
|
o.taxes_to_csv()
|
|
o.fiscal_pos_map_to_csv()
|