Skip to content
Snippets Groups Projects
Commit 300c5c36ab84 authored by Jérémie Gavrel's avatar Jérémie Gavrel
Browse files

Can now use <div class="oe_analytic" prefix="prefix" /> in order to place...

Can now use <div class="oe_analytic" prefix="prefix" /> in order to place every remaining field associated with a structure in the view. Added a README.

Also added a config check on module load.
parent 799b9da434a7
No related branches found
No related tags found
No related merge requests found
......@@ -20,7 +20,7 @@
orm_model_name = nmspc.get('_name', False)
if orm_model_name is False:
orm_model_name = nmspc.get('_inherit')
analytic = {'a': orm_model_name}
analytic = {'a': orm_model_name.replace('.', '_')}
elif isinstance(analytic, basestring):
analytic = {'a': analytic}
nmspc['_analytic'] = analytic
......
README 0 → 100644
== Configure your OpenERP server for analytic fields ==
By default, up to 5 analytic dimensions can be associated with an object.
You can increase this number by setting an option in the configuration file:
[analytic]
analytic_size = 10
== Add analytic fields to a model ==
At the beginning of the source file, import the MetaAnalytic metaclass:
from openerp.addons.analytic_structure.MetaAnalytic import MetaAnalytic
Inside your Model class, define MetaAnalytic to be used as metaclass:
__metaclass__ = MetaAnalytic
Then, add the _analytic attribute to your class.
Use the analytic fields associated with the model:
_analytic = True
Use analytic fields associated with another model:
_analytic = 'account_move_line'
Use several analytic field structures, associated with different prefixes:
_analytic = {
'a': 'account_asset_asset',
't': 'account_move_line',
}
== Add analytic fields to a view ==
Analytic fields can be added to the view individually, like any other field:
<field name="a1_id" />
'a' is the prefix associated with the structure. By default, it is 'a'.
'1' is the dimension's ordering as defined by the analytic structure.
You can also use a div to insert every analytic field within a given structure
(defined by its prefix) that wasn't explicitly placed in the view.
<div class="oe_analytic" required="1" prefix="t" />
The class, oe_analytic, mark the div that will be replaced by analytic fields.
The prefix can be omitted for a structure that uses the default prefix 'a'.
Any other attribute will be propagated to the analytic fields.
Warning: analytic fields should generally not be used inside nested sub-views.
If possible, create a separate record and use the context to specify the view:
<field name="order_line" colspan="4" nolabel="1" context="{
'form_view_ref' : 'module.view_id',
'tree_view_ref' : 'model.view_id'
}"/>
......@@ -19,6 +19,17 @@
#
##############################################################################
# Before loading the module, if the analytic_size option is given, check it.
# Its value must be an integer greater or equal to the default value.
from openerp.tools import config
try:
analytic_size = int(config.get_misc('analytic', 'analytic_size', 5))
assert analytic_size > 5
except (ValueError, AssertionError):
config.parser.error("analytic_size must be an integer greater/equal to 5")
import MetaAnalytic
import analytic_code
import analytic_dimension
......
......@@ -42,6 +42,9 @@
'analytic_dimension.xml',
],
#'demo_xml': [],
'css': [
'static/src/css/analytic_structure.css',
],
'test': [],
'installable': True,
'active': False,
......
......@@ -106,6 +106,7 @@
"""Show or hide used/unused analytic fields."""
ans_dict = self.get_dimensions_names(cr, uid, model, context=context)
found_fields = {slot: False for slot in ans_dict}
regex = '{0}(\d+)_id'.format(prefix)
path = "//field[re:match(@name, '{0}')]".format(regex)
......@@ -117,10 +118,13 @@
for match in matches:
name = match.get('name')
slot = re.search(regex, name).group(1)
is_invisible = not slot in ans_dict
if is_invisible:
if slot in found_fields:
# The analytic field is used and has been found in the view.
found_fields[slot] = True
else:
# No analytic structure defined for this field, hide it.
modifiers = json.loads(match.get('modifiers', '{}'))
modifiers['invisible'] = modifiers['tree_invisible'] = True
modifiers['required'] = False
match.set('modifiers', json.dumps(modifiers))
......@@ -122,6 +126,49 @@
modifiers = json.loads(match.get('modifiers', '{}'))
modifiers['invisible'] = modifiers['tree_invisible'] = True
modifiers['required'] = False
match.set('modifiers', json.dumps(modifiers))
# Look for a div with the 'oe_analytic' class and the right prefix.
if prefix == 'a':
prefix_cond = '(@prefix="a" or not(@prefix))'
else:
prefix_cond = '@prefix="{pfx}"'.format(pfx=prefix)
condition = 'contains(@class, "oe_analytic") and ' + prefix_cond
parent_matches = doc.xpath('//div[{cond}]/..'.format(cond=condition))
if parent_matches:
parent = parent_matches[0]
div = parent.xpath("//div[{cond}]".format(cond=condition))[0]
for index, child in enumerate(parent):
if child == div:
break
next_children = parent[index + 1:]
del parent[index:]
# Get all fields that are in the structure but not in the view.
sorted_fields = found_fields.items()
sorted_fields.sort(key=lambda i: int(i[0]))
div_fields = [
'{pfx}{n}_id'.format(pfx=prefix, n=slot)
for slot, found in sorted_fields if not found
]
# First, we have to load the definitions for those fields.
div_fields_def = self.pool.get(view['model']).fields_get(
cr, uid, div_fields, context=context
)
view['fields'].update(div_fields_def)
# Now we can insert the fields in the view's architecture.
for field in div_fields:
attrs = {'name': field}
for attr, value in div.attrib.iteritems():
if attr in ['class', 'prefix']:
continue
attrs[attr] = value
parent.append(etree.Element('field', attrs))
parent.extend(next_children)
view['arch'] = etree.tostring(doc)
......@@ -127,2 +174,3 @@
view['arch'] = etree.tostring(doc)
return view
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment