[MERGE] forward port of branch 8.0 up to 19b5ba2
This commit is contained in:
@@ -69,7 +69,8 @@ class bank(osv.osv):
|
||||
# No liquidity account exists, no template available
|
||||
if not ids: continue
|
||||
|
||||
ref_acc_bank = obj_acc.browse(cr, uid, ids[0], context=context).parent_id
|
||||
sibbling_acc_bank = obj_acc.browse(cr, uid, ids[0], context=context)
|
||||
ref_acc_bank = sibbling_acc_bank.parent_id
|
||||
while True:
|
||||
new_code = str(ref_acc_bank.code.ljust(dig-len(str(current_num)), '0')) + str(current_num)
|
||||
ids = obj_acc.search(cr, uid, [('code', '=', new_code), ('company_id', '=', bank.company_id.id)])
|
||||
@@ -81,7 +82,7 @@ class bank(osv.osv):
|
||||
'name': name,
|
||||
'code': new_code,
|
||||
'type': 'liquidity',
|
||||
'user_type': ref_acc_bank.user_type.id,
|
||||
'user_type': sibbling_acc_bank.user_type.id,
|
||||
'reconcile': False,
|
||||
'parent_id': ref_acc_bank.id,
|
||||
'company_id': bank.company_id.id,
|
||||
|
||||
@@ -342,7 +342,6 @@
|
||||
<filter string="New Mail" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Interviewer" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Survey" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'survey_id'}"/>
|
||||
<filter string="Status" name="group_state" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/>
|
||||
</group>
|
||||
</search>
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
# the used qemu-kernel doesn't work well with this library, so get rid of it
|
||||
#/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so
|
||||
|
||||
@@ -59,7 +59,11 @@ umount "${MOUNT_POINT}"
|
||||
|
||||
# from http://paulscott.co.za/blog/full-raspberry-pi-raspbian-emulation-with-qemu/
|
||||
# ssh pi@localhost -p10022
|
||||
qemu-system-arm -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" -hda posbox.img -net user,hostfwd=tcp::10022-:22,hostfwd=tcp::18069-:8069 -net nic
|
||||
QEMU_OPTS=(-kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append 'root=/dev/sda2 panic=1 rootfstype=ext4 rw' -hda posbox.img -net user,hostfwd=tcp::10022-:22,hostfwd=tcp::18069-:8069 -net nic)
|
||||
if [ -z ${DISPLAY:-} ] ; then
|
||||
QEMU_OPTS+=(-nographic)
|
||||
fi
|
||||
qemu-system-arm "${QEMU_OPTS[@]}"
|
||||
|
||||
mount "${LOOP_MAPPER_PATH}" "${MOUNT_POINT}"
|
||||
cp -av "${OVERWRITE_FILES_AFTER_INIT_DIR}"/* "${MOUNT_POINT}"
|
||||
|
||||
@@ -188,7 +188,7 @@ class Website(openerp.addons.web.controllers.main.Home):
|
||||
request.registry['website.menu'].create(
|
||||
request.cr, request.uid, {
|
||||
'name': path,
|
||||
'url': "/page/" + xml_id,
|
||||
'url': "/page/" + xml_id[8:],
|
||||
'parent_id': request.website.menu_id.id,
|
||||
'website_id': request.website.id,
|
||||
}, context=request.context)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
<record id="menu_contactus" model="website.menu">
|
||||
<field name="name">Contact us</field>
|
||||
<field name="url">/page/website.contactus</field>
|
||||
<field name="url">/page/contactus</field>
|
||||
<field name="parent_id" ref="website.main_menu"/>
|
||||
<field name="sequence" type="int">60</field>
|
||||
<field name="website_id" ref="default_website"/>
|
||||
@@ -79,7 +79,7 @@
|
||||
</record>
|
||||
<record id="action_website_homepage" model="ir.actions.act_url">
|
||||
<field name="name">Website Homepage</field>
|
||||
<field name="url">/page/website.homepage</field>
|
||||
<field name="url">/page/homepage</field>
|
||||
<field name="target">self</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -134,16 +134,15 @@
|
||||
|
||||
<template id="submenu" name="Submenu">
|
||||
<li t-if="not submenu.child_id" t-att-class="
|
||||
((submenu.url and submenu.url != '/' and request.httprequest.path.startswith(submenu.url)) or
|
||||
request.httprequest.path == submenu.url) and 'active'
|
||||
'active' if submenu.url and submenu.url != '/' and request.httprequest.path == submenu.url.replace('/page/website.', '/page/') else None
|
||||
">
|
||||
<a t-att-href="(website.menu_id.child_id[0] == submenu) and '/' or submenu.url" t-ignore="true" t-att-target="'_blank' if submenu.new_window else None">
|
||||
<span t-field="submenu.name"/>
|
||||
</a>
|
||||
</li>
|
||||
<li t-if="submenu.child_id" t-attf-class="dropdown #{
|
||||
((submenu.url and submenu.url != '/' and [1 for submenu in submenu.child_id if request.httprequest.path.startswith(submenu.url)]) or
|
||||
request.httprequest.path == submenu.url) and 'active'
|
||||
(submenu.url and submenu.url != '/' and any([request.httprequest.path == child.url.replace('/page/website.', '/page/') for child in submenu.child_id]) or
|
||||
request.httprequest.path == submenu.url.replace('/page/website.', '/page/')) and 'active'
|
||||
}">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||
<span t-field="submenu.name"/> <span class="caret" t-ignore="true"></span>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<record id="action_open_website" model="ir.actions.act_url">
|
||||
<field name="name">Website Contact Form</field>
|
||||
<field name="target">self</field>
|
||||
<field name="url">/page/website.contactus</field>
|
||||
<field name="url">/page/contactus</field>
|
||||
</record>
|
||||
<record id="base.open_menu" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_open_website"/>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<record id="action_open_website" model="ir.actions.act_url">
|
||||
<field name="name">Website About</field>
|
||||
<field name="target">self</field>
|
||||
<field name="url">/page/website.aboutus</field>
|
||||
<field name="url">/page/aboutus</field>
|
||||
</record>
|
||||
<record id="base.open_menu" model="ir.actions.todo">
|
||||
<field name="action_id" ref="action_open_website"/>
|
||||
|
||||
@@ -148,6 +148,7 @@ class res_users(osv.osv):
|
||||
}
|
||||
_name = "res.users"
|
||||
_description = 'Users'
|
||||
_order = 'name, login'
|
||||
|
||||
def _set_new_password(self, cr, uid, id, name, value, args, context=None):
|
||||
if value is False:
|
||||
|
||||
@@ -104,6 +104,21 @@ class test_search(common.TransactionCase):
|
||||
self.assertEqual(test_user_ids, expected_ids, 'search on res_users did not provide expected ids or expected order')
|
||||
users_obj._order = old_order
|
||||
|
||||
def test_11_indirect_inherits_m2order(self):
|
||||
registry, cr, uid = self.registry, self.cr, self.uid
|
||||
Cron = registry('ir.cron')
|
||||
Users = registry('res.users')
|
||||
|
||||
user_ids = {}
|
||||
cron_ids = {}
|
||||
for u in 'BAC':
|
||||
user_ids[u] = Users.create(cr, uid, {'name': u, 'login': u})
|
||||
cron_ids[u] = Cron.create(cr, uid, {'name': u, 'user_id': user_ids[u]})
|
||||
|
||||
ids = Cron.search(cr, uid, [('id', 'in', cron_ids.values())], order='user_id')
|
||||
expected_ids = [cron_ids[l] for l in 'ABC']
|
||||
self.assertEqual(ids, expected_ids)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
|
||||
+59
-54
@@ -1940,7 +1940,7 @@ class BaseModel(object):
|
||||
gb_function = split[1] if len(split) == 2 else None
|
||||
temporal = field_type in ('date', 'datetime')
|
||||
tz_convert = field_type == 'datetime' and context.get('tz') in pytz.all_timezones
|
||||
qualified_field = self._inherits_join_calc(split[0], query)
|
||||
qualified_field = self._inherits_join_calc(self._table, split[0], query)
|
||||
if temporal:
|
||||
display_formats = {
|
||||
# Careful with week/year formats:
|
||||
@@ -2096,7 +2096,7 @@ class BaseModel(object):
|
||||
if getattr(self._fields[f].base_field.column, '_classic_write', False)
|
||||
]
|
||||
|
||||
field_formatter = lambda f: (self._fields[f].group_operator or 'sum', self._inherits_join_calc(f, query), f)
|
||||
field_formatter = lambda f: (self._fields[f].group_operator or 'sum', self._inherits_join_calc(self._table, f, query), f)
|
||||
select_terms = ["%s(%s) AS %s" % field_formatter(f) for f in aggregated_fields]
|
||||
|
||||
for gb in annotated_groupbys:
|
||||
@@ -2170,17 +2170,18 @@ class BaseModel(object):
|
||||
parent_alias, parent_alias_statement = query.add_join((current_model._table, parent_model._table, inherits_field, 'id', inherits_field), implicit=True)
|
||||
return parent_alias
|
||||
|
||||
def _inherits_join_calc(self, field, query):
|
||||
def _inherits_join_calc(self, alias, field, query):
|
||||
"""
|
||||
Adds missing table select and join clause(s) to ``query`` for reaching
|
||||
the field coming from an '_inherits' parent table (no duplicates).
|
||||
|
||||
:param alias: name of the initial SQL alias
|
||||
:param field: name of inherited field to reach
|
||||
:param query: query object on which the JOIN should be added
|
||||
:return: qualified name of field, to be used in SELECT clause
|
||||
"""
|
||||
# INVARIANT: alias is the SQL alias of model._table in query
|
||||
model, alias = self, self._table
|
||||
model = self
|
||||
while field in model._inherit_fields and field not in model._columns:
|
||||
# retrieve the parent model where field is inherited from
|
||||
parent_model_name = model._inherit_fields[field][0]
|
||||
@@ -3284,7 +3285,7 @@ class BaseModel(object):
|
||||
def qualify(field):
|
||||
col = field.name
|
||||
if field.inherited:
|
||||
res = self._inherits_join_calc(field.name, query)
|
||||
res = self._inherits_join_calc(self._table, field.name, query)
|
||||
else:
|
||||
res = '"%s"."%s"' % (self._table, col)
|
||||
if field.type == 'binary' and (context.get('bin_size') or context.get('bin_size_' + col)):
|
||||
@@ -4533,9 +4534,9 @@ class BaseModel(object):
|
||||
for inherited_model in self._inherits:
|
||||
rule_where_clause, rule_where_clause_params, rule_tables = rule_obj.domain_get(cr, uid, inherited_model, mode, context=context)
|
||||
apply_rule(rule_where_clause, rule_where_clause_params, rule_tables,
|
||||
parent_model=inherited_model)
|
||||
parent_model=inherited_model)
|
||||
|
||||
def _generate_m2o_order_by(self, order_field, query):
|
||||
def _generate_m2o_order_by(self, alias, order_field, query, reverse_direction):
|
||||
"""
|
||||
Add possibly missing JOIN to ``query`` and generate the ORDER BY clause for m2o fields,
|
||||
either native m2o fields or function/related fields that are stored, including
|
||||
@@ -4545,10 +4546,10 @@ class BaseModel(object):
|
||||
"""
|
||||
if order_field not in self._columns and order_field in self._inherit_fields:
|
||||
# also add missing joins for reaching the table containing the m2o field
|
||||
qualified_field = self._inherits_join_calc(order_field, query)
|
||||
qualified_field = self._inherits_join_calc(alias, order_field, query)
|
||||
order_field_column = self._inherit_fields[order_field][2]
|
||||
else:
|
||||
qualified_field = '"%s"."%s"' % (self._table, order_field)
|
||||
qualified_field = '"%s"."%s"' % (alias, order_field)
|
||||
order_field_column = self._columns[order_field]
|
||||
|
||||
assert order_field_column._type == 'many2one', 'Invalid field passed to _generate_m2o_order_by()'
|
||||
@@ -4564,19 +4565,59 @@ class BaseModel(object):
|
||||
if not regex_order.match(m2o_order):
|
||||
# _order is complex, can't use it here, so we default to _rec_name
|
||||
m2o_order = dest_model._rec_name
|
||||
else:
|
||||
# extract the field names, to be able to qualify them and add desc/asc
|
||||
m2o_order_list = []
|
||||
for order_part in m2o_order.split(","):
|
||||
m2o_order_list.append(order_part.strip().split(" ", 1)[0].strip())
|
||||
m2o_order = m2o_order_list
|
||||
|
||||
# Join the dest m2o table if it's not joined yet. We use [LEFT] OUTER join here
|
||||
# as we don't want to exclude results that have NULL values for the m2o
|
||||
src_table, src_field = qualified_field.replace('"', '').split('.', 1)
|
||||
dst_alias, dst_alias_statement = query.add_join((src_table, dest_model._table, src_field, 'id', src_field), implicit=False, outer=True)
|
||||
qualify = lambda field: '"%s"."%s"' % (dst_alias, field)
|
||||
return map(qualify, m2o_order) if isinstance(m2o_order, list) else qualify(m2o_order)
|
||||
return dest_model._generate_order_by_inner(dst_alias, m2o_order, query,
|
||||
reverse_direction=reverse_direction)
|
||||
|
||||
def _generate_order_by_inner(self, alias, order_spec, query, reverse_direction=False):
|
||||
order_by_elements = []
|
||||
self._check_qorder(order_spec)
|
||||
for order_part in order_spec.split(','):
|
||||
order_split = order_part.strip().split(' ')
|
||||
order_field = order_split[0].strip()
|
||||
order_direction = order_split[1].strip().upper() if len(order_split) == 2 else ''
|
||||
if reverse_direction:
|
||||
order_direction = 'ASC' if order_direction == 'DESC' else 'DESC'
|
||||
do_reverse = order_direction == 'DESC'
|
||||
order_column = None
|
||||
inner_clauses = []
|
||||
add_dir = False
|
||||
if order_field == 'id':
|
||||
order_by_elements.append('"%s"."%s" %s' % (alias, order_field, order_direction))
|
||||
elif order_field in self._columns:
|
||||
order_column = self._columns[order_field]
|
||||
if order_column._classic_read:
|
||||
inner_clauses = ['"%s"."%s"' % (alias, order_field)]
|
||||
add_dir = True
|
||||
elif order_column._type == 'many2one':
|
||||
inner_clauses = self._generate_m2o_order_by(alias, order_field, query, do_reverse)
|
||||
else:
|
||||
continue # ignore non-readable or "non-joinable" fields
|
||||
elif order_field in self._inherit_fields:
|
||||
parent_obj = self.pool[self._inherit_fields[order_field][3]]
|
||||
order_column = parent_obj._columns[order_field]
|
||||
if order_column._classic_read:
|
||||
inner_clauses = [self._inherits_join_calc(alias, order_field, query)]
|
||||
add_dir = True
|
||||
elif order_column._type == 'many2one':
|
||||
inner_clauses = self._generate_m2o_order_by(alias, order_field, query, do_reverse)
|
||||
else:
|
||||
continue # ignore non-readable or "non-joinable" fields
|
||||
else:
|
||||
raise ValueError(_("Sorting field %s not found on model %s") % (order_field, self._name))
|
||||
if order_column and order_column._type == 'boolean':
|
||||
inner_clauses = ["COALESCE(%s, false)" % inner_clauses[0]]
|
||||
|
||||
for clause in inner_clauses:
|
||||
if add_dir:
|
||||
order_by_elements.append("%s %s" % (clause, order_direction))
|
||||
else:
|
||||
order_by_elements.append(clause)
|
||||
return order_by_elements
|
||||
|
||||
def _generate_order_by(self, order_spec, query):
|
||||
"""
|
||||
@@ -4588,43 +4629,7 @@ class BaseModel(object):
|
||||
order_by_clause = ''
|
||||
order_spec = order_spec or self._order
|
||||
if order_spec:
|
||||
order_by_elements = []
|
||||
self._check_qorder(order_spec)
|
||||
for order_part in order_spec.split(','):
|
||||
order_split = order_part.strip().split(' ')
|
||||
order_field = order_split[0].strip()
|
||||
order_direction = order_split[1].strip() if len(order_split) == 2 else ''
|
||||
order_column = None
|
||||
inner_clause = None
|
||||
if order_field == 'id':
|
||||
order_by_elements.append('"%s"."%s" %s' % (self._table, order_field, order_direction))
|
||||
elif order_field in self._columns:
|
||||
order_column = self._columns[order_field]
|
||||
if order_column._classic_read:
|
||||
inner_clause = '"%s"."%s"' % (self._table, order_field)
|
||||
elif order_column._type == 'many2one':
|
||||
inner_clause = self._generate_m2o_order_by(order_field, query)
|
||||
else:
|
||||
continue # ignore non-readable or "non-joinable" fields
|
||||
elif order_field in self._inherit_fields:
|
||||
parent_obj = self.pool[self._inherit_fields[order_field][3]]
|
||||
order_column = parent_obj._columns[order_field]
|
||||
if order_column._classic_read:
|
||||
inner_clause = self._inherits_join_calc(order_field, query)
|
||||
elif order_column._type == 'many2one':
|
||||
inner_clause = self._generate_m2o_order_by(order_field, query)
|
||||
else:
|
||||
continue # ignore non-readable or "non-joinable" fields
|
||||
else:
|
||||
raise ValueError(_("Sorting field %s not found on model %s") % ( order_field, self._name))
|
||||
if order_column and order_column._type == 'boolean':
|
||||
inner_clause = "COALESCE(%s, false)" % inner_clause
|
||||
if inner_clause:
|
||||
if isinstance(inner_clause, list):
|
||||
for clause in inner_clause:
|
||||
order_by_elements.append("%s %s" % (clause, order_direction))
|
||||
else:
|
||||
order_by_elements.append("%s %s" % (inner_clause, order_direction))
|
||||
order_by_elements = self._generate_order_by_inner(self._table, order_spec, query)
|
||||
if order_by_elements:
|
||||
order_by_clause = ",".join(order_by_elements)
|
||||
|
||||
|
||||
@@ -988,12 +988,11 @@ class many2many(_column):
|
||||
|
||||
wquery = obj._where_calc(cr, user, domain, context=context)
|
||||
obj._apply_ir_rules(cr, user, wquery, 'read', context=context)
|
||||
order_by = obj._generate_order_by(None, wquery)
|
||||
from_c, where_c, where_params = wquery.get_sql()
|
||||
if where_c:
|
||||
where_c = ' AND ' + where_c
|
||||
|
||||
order_by = ' ORDER BY "%s".%s' %(obj._table, obj._order.split(',')[0])
|
||||
|
||||
limit_str = ''
|
||||
if self._limit is not None:
|
||||
limit_str = ' LIMIT %d' % self._limit
|
||||
|
||||
Reference in New Issue
Block a user