mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 01:52:07 +02:00
17.0 vanilla
This commit is contained in:
parent
2e65bf056a
commit
df627a6bba
328 changed files with 578149 additions and 759311 deletions
|
|
@ -28,7 +28,7 @@ except ImportError:
|
|||
import odoo
|
||||
from . import pycompat
|
||||
from .config import config
|
||||
from .misc import file_open, unquote, ustr, SKIPPED_ELEMENT_TYPES
|
||||
from .misc import file_open, file_path, SKIPPED_ELEMENT_TYPES
|
||||
from .translate import _
|
||||
from odoo import SUPERUSER_ID, api
|
||||
from odoo.exceptions import ValidationError
|
||||
|
|
@ -155,9 +155,10 @@ def _eval_xml(self, node, env):
|
|||
# after that, only text content makes sense
|
||||
data = pycompat.to_text(data)
|
||||
if t == 'file':
|
||||
from ..modules import module
|
||||
path = data.strip()
|
||||
if not module.get_module_resource(self.module, path):
|
||||
try:
|
||||
file_path(os.path.join(self.module, path))
|
||||
except FileNotFoundError:
|
||||
raise IOError("No such file or directory: '%s' in %s" % (
|
||||
path, self.module))
|
||||
return '%s,%s' % (self.module, path)
|
||||
|
|
@ -229,7 +230,7 @@ class xml_import(object):
|
|||
**safe_eval(context, {
|
||||
'ref': self.id_get,
|
||||
**(eval_context or {})
|
||||
})
|
||||
}),
|
||||
}
|
||||
)
|
||||
return self.env
|
||||
|
|
@ -272,160 +273,12 @@ form: module.record_id""" % (xml_id,)
|
|||
if records:
|
||||
records.unlink()
|
||||
|
||||
def _tag_report(self, rec):
|
||||
res = {}
|
||||
for dest,f in (('name','string'),('model','model'),('report_name','name')):
|
||||
res[dest] = rec.get(f)
|
||||
assert res[dest], "Attribute %s of report is empty !" % (f,)
|
||||
for field, dest in (('attachment', 'attachment'),
|
||||
('attachment_use', 'attachment_use'),
|
||||
('usage', 'usage'),
|
||||
('file', 'report_file'),
|
||||
('report_type', 'report_type'),
|
||||
('parser', 'parser'),
|
||||
('print_report_name', 'print_report_name'),
|
||||
):
|
||||
if rec.get(field):
|
||||
res[dest] = rec.get(field)
|
||||
if rec.get('auto'):
|
||||
res['auto'] = safe_eval(rec.get('auto','False'))
|
||||
if rec.get('header'):
|
||||
res['header'] = safe_eval(rec.get('header','False'))
|
||||
|
||||
res['multi'] = rec.get('multi') and safe_eval(rec.get('multi','False'))
|
||||
|
||||
xml_id = rec.get('id','')
|
||||
self._test_xml_id(xml_id)
|
||||
warnings.warn(f"The <report> tag is deprecated, use a <record> tag for {xml_id!r}.", DeprecationWarning)
|
||||
|
||||
if rec.get('groups'):
|
||||
g_names = rec.get('groups','').split(',')
|
||||
groups_value = []
|
||||
for group in g_names:
|
||||
if group.startswith('-'):
|
||||
group_id = self.id_get(group[1:])
|
||||
groups_value.append(odoo.Command.unlink(group_id))
|
||||
else:
|
||||
group_id = self.id_get(group)
|
||||
groups_value.append(odoo.Command.link(group_id))
|
||||
res['groups_id'] = groups_value
|
||||
if rec.get('paperformat'):
|
||||
pf_name = rec.get('paperformat')
|
||||
pf_id = self.id_get(pf_name)
|
||||
res['paperformat_id'] = pf_id
|
||||
|
||||
xid = self.make_xml_id(xml_id)
|
||||
data = dict(xml_id=xid, values=res, noupdate=self.noupdate)
|
||||
report = self.env['ir.actions.report']._load_records([data], self.mode == 'update')
|
||||
self.idref[xml_id] = report.id
|
||||
|
||||
if not rec.get('menu') or safe_eval(rec.get('menu','False')):
|
||||
report.create_action()
|
||||
elif self.mode=='update' and safe_eval(rec.get('menu','False'))==False:
|
||||
# Special check for report having attribute menu=False on update
|
||||
report.unlink_action()
|
||||
return report.id
|
||||
|
||||
def _tag_function(self, rec):
|
||||
if self.noupdate and self.mode != 'init':
|
||||
return
|
||||
env = self.get_env(rec)
|
||||
_eval_xml(self, rec, env)
|
||||
|
||||
def _tag_act_window(self, rec):
|
||||
name = rec.get('name')
|
||||
xml_id = rec.get('id','')
|
||||
self._test_xml_id(xml_id)
|
||||
warnings.warn(f"The <act_window> tag is deprecated, use a <record> for {xml_id!r}.", DeprecationWarning)
|
||||
view_id = False
|
||||
if rec.get('view_id'):
|
||||
view_id = self.id_get(rec.get('view_id'))
|
||||
domain = rec.get('domain') or '[]'
|
||||
res_model = rec.get('res_model')
|
||||
binding_model = rec.get('binding_model')
|
||||
view_mode = rec.get('view_mode') or 'tree,form'
|
||||
usage = rec.get('usage')
|
||||
limit = rec.get('limit')
|
||||
uid = self.env.user.id
|
||||
|
||||
# Act_window's 'domain' and 'context' contain mostly literals
|
||||
# but they can also refer to the variables provided below
|
||||
# in eval_context, so we need to eval() them before storing.
|
||||
# Among the context variables, 'active_id' refers to
|
||||
# the currently selected items in a list view, and only
|
||||
# takes meaning at runtime on the client side. For this
|
||||
# reason it must remain a bare variable in domain and context,
|
||||
# even after eval() at server-side. We use the special 'unquote'
|
||||
# class to achieve this effect: a string which has itself, unquoted,
|
||||
# as representation.
|
||||
active_id = unquote("active_id")
|
||||
active_ids = unquote("active_ids")
|
||||
active_model = unquote("active_model")
|
||||
|
||||
# Include all locals() in eval_context, for backwards compatibility
|
||||
eval_context = {
|
||||
'name': name,
|
||||
'xml_id': xml_id,
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_id': view_id,
|
||||
'domain': domain,
|
||||
'res_model': res_model,
|
||||
'src_model': binding_model,
|
||||
'view_mode': view_mode,
|
||||
'usage': usage,
|
||||
'limit': limit,
|
||||
'uid': uid,
|
||||
'active_id': active_id,
|
||||
'active_ids': active_ids,
|
||||
'active_model': active_model,
|
||||
}
|
||||
context = self.get_env(rec, eval_context).context
|
||||
|
||||
try:
|
||||
domain = safe_eval(domain, eval_context)
|
||||
except (ValueError, NameError):
|
||||
# Some domains contain references that are only valid at runtime at
|
||||
# client-side, so in that case we keep the original domain string
|
||||
# as it is. We also log it, just in case.
|
||||
_logger.debug('Domain value (%s) for element with id "%s" does not parse '\
|
||||
'at server-side, keeping original string, in case it\'s meant for client side only',
|
||||
domain, xml_id or 'n/a', exc_info=True)
|
||||
res = {
|
||||
'name': name,
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_id': view_id,
|
||||
'domain': domain,
|
||||
'context': context,
|
||||
'res_model': res_model,
|
||||
'view_mode': view_mode,
|
||||
'usage': usage,
|
||||
'limit': limit,
|
||||
}
|
||||
|
||||
if rec.get('groups'):
|
||||
g_names = rec.get('groups','').split(',')
|
||||
groups_value = []
|
||||
for group in g_names:
|
||||
if group.startswith('-'):
|
||||
group_id = self.id_get(group[1:])
|
||||
groups_value.append(odoo.Command.unlink(group_id))
|
||||
else:
|
||||
group_id = self.id_get(group)
|
||||
groups_value.append(odoo.Command.link(group_id))
|
||||
res['groups_id'] = groups_value
|
||||
|
||||
if rec.get('target'):
|
||||
res['target'] = rec.get('target','')
|
||||
if binding_model:
|
||||
res['binding_model_id'] = self.env['ir.model']._get(binding_model).id
|
||||
res['binding_type'] = rec.get('binding_type') or 'action'
|
||||
views = rec.get('binding_views')
|
||||
if views is not None:
|
||||
res['binding_view_types'] = views
|
||||
xid = self.make_xml_id(xml_id)
|
||||
data = dict(xml_id=xid, values=res, noupdate=self.noupdate)
|
||||
self.env['ir.actions.act_window']._load_records([data], self.mode == 'update')
|
||||
|
||||
def _tag_menuitem(self, rec, parent=None):
|
||||
rec_id = rec.attrib["id"]
|
||||
self._test_xml_id(rec_id)
|
||||
|
|
@ -556,7 +409,7 @@ form: module.record_id""" % (xml_id,)
|
|||
if f_search:
|
||||
idref2 = _get_idref(self, env, f_model, self.idref)
|
||||
q = safe_eval(f_search, idref2)
|
||||
assert f_model, 'Define an attribute model="..." in your .XML file !'
|
||||
assert f_model, 'Define an attribute model="..." in your .XML file!'
|
||||
# browse the objects searched
|
||||
s = env[f_model].search(q)
|
||||
# column definitions of the "local" object
|
||||
|
|
@ -602,6 +455,10 @@ form: module.record_id""" % (xml_id,)
|
|||
res[f_name] = f_val
|
||||
if extra_vals:
|
||||
res.update(extra_vals)
|
||||
if 'sequence' not in res and 'sequence' in model._fields:
|
||||
sequence = self.next_sequence()
|
||||
if sequence:
|
||||
res['sequence'] = sequence
|
||||
|
||||
data = dict(xml_id=xid, values=res, noupdate=self.noupdate)
|
||||
record = model._load_records([data], self.mode == 'update')
|
||||
|
|
@ -702,6 +559,7 @@ form: module.record_id""" % (xml_id,)
|
|||
|
||||
self.envs.append(self.get_env(el))
|
||||
self._noupdate.append(nodeattr2bool(el, 'noupdate', self.noupdate))
|
||||
self._sequences.append(0 if nodeattr2bool(el, 'auto_sequence', False) else None)
|
||||
try:
|
||||
f(rec)
|
||||
except ParseError:
|
||||
|
|
@ -724,6 +582,7 @@ form: module.record_id""" % (xml_id,)
|
|||
finally:
|
||||
self._noupdate.pop()
|
||||
self.envs.pop()
|
||||
self._sequences.pop()
|
||||
|
||||
@property
|
||||
def env(self):
|
||||
|
|
@ -733,12 +592,19 @@ form: module.record_id""" % (xml_id,)
|
|||
def noupdate(self):
|
||||
return self._noupdate[-1]
|
||||
|
||||
def __init__(self, cr, module, idref, mode, noupdate=False, xml_filename=None):
|
||||
def next_sequence(self):
|
||||
value = self._sequences[-1]
|
||||
if value is not None:
|
||||
value = self._sequences[-1] = value + 10
|
||||
return value
|
||||
|
||||
def __init__(self, env, module, idref, mode, noupdate=False, xml_filename=None):
|
||||
self.mode = mode
|
||||
self.module = module
|
||||
self.envs = [odoo.api.Environment(cr, SUPERUSER_ID, {})]
|
||||
self.envs = [env(context=dict(env.context, lang=None))]
|
||||
self.idref = {} if idref is None else idref
|
||||
self._noupdate = [noupdate]
|
||||
self._sequences = []
|
||||
self.xml_filename = xml_filename
|
||||
self._tags = {
|
||||
'record': self._tag_record,
|
||||
|
|
@ -746,8 +612,6 @@ form: module.record_id""" % (xml_id,)
|
|||
'function': self._tag_function,
|
||||
'menuitem': self._tag_menuitem,
|
||||
'template': self._tag_template,
|
||||
'report': self._tag_report,
|
||||
'act_window': self._tag_act_window,
|
||||
|
||||
**dict.fromkeys(self.DATA_ROOTS, self._tag_root)
|
||||
}
|
||||
|
|
@ -757,32 +621,33 @@ form: module.record_id""" % (xml_id,)
|
|||
self._tag_root(de)
|
||||
DATA_ROOTS = ['odoo', 'data', 'openerp']
|
||||
|
||||
def convert_file(cr, module, filename, idref, mode='update', noupdate=False, kind=None, pathname=None):
|
||||
def convert_file(env, module, filename, idref, mode='update', noupdate=False, kind=None, pathname=None):
|
||||
if pathname is None:
|
||||
pathname = os.path.join(module, filename)
|
||||
ext = os.path.splitext(filename)[1].lower()
|
||||
|
||||
with file_open(pathname, 'rb') as fp:
|
||||
if ext == '.csv':
|
||||
convert_csv_import(cr, module, pathname, fp.read(), idref, mode, noupdate)
|
||||
convert_csv_import(env, module, pathname, fp.read(), idref, mode, noupdate)
|
||||
elif ext == '.sql':
|
||||
convert_sql_import(cr, fp)
|
||||
convert_sql_import(env, fp)
|
||||
elif ext == '.xml':
|
||||
convert_xml_import(cr, module, fp, idref, mode, noupdate)
|
||||
convert_xml_import(env, module, fp, idref, mode, noupdate)
|
||||
elif ext == '.js':
|
||||
pass # .js files are valid but ignored here.
|
||||
else:
|
||||
raise ValueError("Can't load unknown file type %s.", filename)
|
||||
|
||||
def convert_sql_import(cr, fp):
|
||||
cr.execute(fp.read()) # pylint: disable=sql-injection
|
||||
def convert_sql_import(env, fp):
|
||||
env.cr.execute(fp.read()) # pylint: disable=sql-injection
|
||||
|
||||
def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init',
|
||||
def convert_csv_import(env, module, fname, csvcontent, idref=None, mode='init',
|
||||
noupdate=False):
|
||||
'''Import csv file :
|
||||
quote: "
|
||||
delimiter: ,
|
||||
encoding: utf-8'''
|
||||
env = env(context=dict(env.context, lang=None))
|
||||
filename, _ext = os.path.splitext(os.path.basename(fname))
|
||||
model = filename.split('-')[0]
|
||||
reader = pycompat.csv_reader(io.BytesIO(csvcontent), quotechar='"', delimiter=',')
|
||||
|
|
@ -805,21 +670,20 @@ def convert_csv_import(cr, module, fname, csvcontent, idref=None, mode='init',
|
|||
'install_filename': fname,
|
||||
'noupdate': noupdate,
|
||||
}
|
||||
env = odoo.api.Environment(cr, SUPERUSER_ID, context)
|
||||
result = env[model].load(fields, datas)
|
||||
result = env[model].with_context(**context).load(fields, datas)
|
||||
if any(msg['type'] == 'error' for msg in result['messages']):
|
||||
# Report failed import and abort module install
|
||||
warning_msg = "\n".join(msg['message'] for msg in result['messages'])
|
||||
raise Exception(_('Module loading %s failed: file %s could not be processed:\n %s') % (module, fname, warning_msg))
|
||||
|
||||
def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate=False, report=None):
|
||||
def convert_xml_import(env, module, xmlfile, idref=None, mode='init', noupdate=False, report=None):
|
||||
doc = etree.parse(xmlfile)
|
||||
schema = os.path.join(config['root_path'], 'import_xml.rng')
|
||||
relaxng = etree.RelaxNG(etree.parse(schema))
|
||||
try:
|
||||
relaxng.assert_(doc)
|
||||
except Exception:
|
||||
_logger.exception("The XML file '%s' does not fit the required schema !", xmlfile.name)
|
||||
_logger.exception("The XML file '%s' does not fit the required schema!", xmlfile.name)
|
||||
if jingtrang:
|
||||
p = subprocess.run(['pyjing', schema, xmlfile.name], stdout=subprocess.PIPE)
|
||||
_logger.warning(p.stdout.decode())
|
||||
|
|
@ -833,5 +697,5 @@ def convert_xml_import(cr, module, xmlfile, idref=None, mode='init', noupdate=Fa
|
|||
xml_filename = xmlfile
|
||||
else:
|
||||
xml_filename = xmlfile.name
|
||||
obj = xml_import(cr, module, idref, mode, noupdate=noupdate, xml_filename=xml_filename)
|
||||
obj = xml_import(env, module, idref, mode, noupdate=noupdate, xml_filename=xml_filename)
|
||||
obj.parse(doc.getroot())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue