diff options
| author | Christophe Simonis <chs@odoo.com> | 2015-08-14 17:26:04 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2015-08-14 17:26:04 +0200 |
| commit | 8d95f6dcdf6e451f32c247bcabd5ce024a158ebe (patch) | |
| tree | 6e3d989c65a4c7090e313a474122fb426cf40896 | |
| parent | e4742f3d1f6b83993f87bbb5a82ff4e01c04bbb0 (diff) | |
| parent | 19b5ba2b08476ea2ede46ab7cf482526c47e62c8 (diff) | |
[MERGE] forward port of branch 8.0 up to 19b5ba2
| -rw-r--r-- | addons/account/account_bank.py | 5 | ||||
| -rw-r--r-- | addons/hr_evaluation/hr_evaluation_view.xml | 1 | ||||
| -rw-r--r-- | addons/point_of_sale/tools/posbox/overwrite_before_init/etc/ld.so.preload | 1 | ||||
| -rwxr-xr-x | addons/point_of_sale/tools/posbox/posbox_create_image.sh | 6 | ||||
| -rw-r--r-- | addons/website/controllers/main.py | 2 | ||||
| -rw-r--r-- | addons/website/data/data.xml | 4 | ||||
| -rw-r--r-- | addons/website/views/website_templates.xml | 7 | ||||
| -rw-r--r-- | addons/website_crm/data/website_crm_data.xml | 2 | ||||
| -rw-r--r-- | addons/website_hr/data/website_hr_data.xml | 2 | ||||
| -rw-r--r-- | openerp/addons/base/res/res_users.py | 1 | ||||
| -rw-r--r-- | openerp/addons/base/tests/test_search.py | 15 | ||||
| -rw-r--r-- | openerp/models.py | 113 | ||||
| -rw-r--r-- | openerp/osv/fields.py | 3 |
13 files changed, 92 insertions, 70 deletions
diff --git a/addons/account/account_bank.py b/addons/account/account_bank.py index 27fc338072e..059940f86ee 100644 --- a/addons/account/account_bank.py +++ b/addons/account/account_bank.py @@ -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, diff --git a/addons/hr_evaluation/hr_evaluation_view.xml b/addons/hr_evaluation/hr_evaluation_view.xml index b91af7b4653..190359bbffd 100644 --- a/addons/hr_evaluation/hr_evaluation_view.xml +++ b/addons/hr_evaluation/hr_evaluation_view.xml @@ -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> diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/ld.so.preload b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/ld.so.preload index 5e9332843b5..cfa850b8356 100644 --- a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/ld.so.preload +++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/ld.so.preload @@ -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 diff --git a/addons/point_of_sale/tools/posbox/posbox_create_image.sh b/addons/point_of_sale/tools/posbox/posbox_create_image.sh index 2a2a0dd9425..9e65410f8fe 100755 --- a/addons/point_of_sale/tools/posbox/posbox_create_image.sh +++ b/addons/point_of_sale/tools/posbox/posbox_create_image.sh @@ -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}" diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index a5a01d41ae9..9d3e0f3aecb 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -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) diff --git a/addons/website/data/data.xml b/addons/website/data/data.xml index 1c1567a310c..519f01844c6 100644 --- a/addons/website/data/data.xml +++ b/addons/website/data/data.xml @@ -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> diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml index 19292f32467..6fc55be8e96 100644 --- a/addons/website/views/website_templates.xml +++ b/addons/website/views/website_templates.xml @@ -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> diff --git a/addons/website_crm/data/website_crm_data.xml b/addons/website_crm/data/website_crm_data.xml index ada2e73e71d..8d6c916fffa 100644 --- a/addons/website_crm/data/website_crm_data.xml +++ b/addons/website_crm/data/website_crm_data.xml @@ -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"/> diff --git a/addons/website_hr/data/website_hr_data.xml b/addons/website_hr/data/website_hr_data.xml index 161b875556a..5afe68add8f 100644 --- a/addons/website_hr/data/website_hr_data.xml +++ b/addons/website_hr/data/website_hr_data.xml @@ -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"/> diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index ed27af14b1d..47ef13dc1b6 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -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: diff --git a/openerp/addons/base/tests/test_search.py b/openerp/addons/base/tests/test_search.py index 4f93eff240c..af14fc88e85 100644 --- a/openerp/addons/base/tests/test_search.py +++ b/openerp/addons/base/tests/test_search.py @@ -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() diff --git a/openerp/models.py b/openerp/models.py index 1ab87134e53..e101da0b5ec 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -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) diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index bcff5a2fadb..415f3272171 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -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 |
