From: Christophe Simonis Date: Tue, 2 Dec 2014 15:18:08 +0000 (+0100) Subject: [MERGE] forward port of branch 8.0 up to 591e329 X-Git-Url: http://git.inspyration.org/?p=odoo%2Fodoo.git;a=commitdiff_plain;h=1d3f8eba879f02da7fc0bb46c9801029eccbc8c8 [MERGE] forward port of branch 8.0 up to 591e329 --- 1d3f8eba879f02da7fc0bb46c9801029eccbc8c8 diff --cc addons/account/account_bank_statement.py index e8e027f,d7e5f8e..8fbce5e --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@@ -834,13 -859,13 +858,13 @@@ class account_statement_operation_templ _description = "Preset for the lines that can be created in a bank statement reconciliation" _columns = { 'name': fields.char('Button Label', required=True), - 'account_id': fields.many2one('account.account', 'Account', ondelete='cascade', domain=[('type','not in',('view','closed','consolidation'))]), + 'account_id': fields.many2one('account.account', 'Account', ondelete='cascade', domain=[('type', 'not in', ('view', 'closed', 'consolidation'))]), - 'label': fields.char('Label'), - 'amount_type': fields.selection([('fixed', 'Fixed'),('percentage_of_total','Percentage of total amount'),('percentage_of_balance', 'Percentage of open balance')], - 'Amount type', required=True), - 'amount': fields.float('Amount', digits_compute=dp.get_precision('Account'), help="The amount will count as a debit if it is negative, as a credit if it is positive (except if amount type is 'Percentage of open balance').", required=True), - 'tax_id': fields.many2one('account.tax', 'Tax', ondelete='restrict', domain=[('type_tax_use', 'in', ['purchase', 'all']), ('parent_id', '=', False)]), + 'label': fields.char('Journal Item Label'), + 'amount_type': fields.selection([('fixed', 'Fixed'),('percentage_of_total','Percentage of total amount'),('percentage_of_balance', 'Percentage of open balance')], 'Amount type', required=True), + 'amount': fields.float('Amount', digits_compute=dp.get_precision('Account'), required=True, help="The amount will count as a debit if it is negative, as a credit if it is positive (except if amount type is 'Percentage of open balance')."), + 'tax_id': fields.many2one('account.tax', 'Tax', ondelete='restrict', domain=[('type_tax_use','in',('purchase','all')), ('parent_id','=',False)]), 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', ondelete='set null', domain=[('type','!=','view'), ('state','not in',('close','cancelled'))]), + 'company_id': fields.many2one('res.company', 'Company', required=True), } _defaults = { 'amount_type': 'percentage_of_balance', diff --cc addons/crm/crm.py index 045b68f,9d12c56..45f84b8 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@@ -69,10 -70,10 +69,10 @@@ class crm_tracking_mixin(osv.AbstractMo _name = 'crm.tracking.mixin' _columns = { - 'campaign_id': fields.many2one('crm.tracking.campaign', 'Campaign', # old domain ="['|',('section_id','=',section_id),('section_id','=',False)]" + 'campaign_id': fields.many2one('crm.tracking.campaign', 'Campaign', # old domain ="['|',('team_id','=',team_id),('team_id','=',False)]" help="This is a name that helps you keep track of your different campaign efforts Ex: Fall_Drive, Christmas_Special"), 'source_id': fields.many2one('crm.tracking.source', 'Source', help="This is the source of the link Ex: Search Engine, another domain, or name of email list"), - 'medium_id': fields.many2one('crm.tracking.medium', 'Channel', help="This is the method of delivery. Ex: Postcard, Email, or Banner Ad"), + 'medium_id': fields.many2one('crm.tracking.medium', 'Channel', help="This is the method of delivery. Ex: Postcard, Email, or Banner Ad", oldname='channel_id'), } def tracking_fields(self): diff --cc addons/crm/crm_lead_view.xml index 158bd1f,e294d76..1e40b52 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@@ -561,14 -546,13 +561,14 @@@ + + domain="['&', ('stage_id.probability', '=', 0), ('stage_id.sequence', '<=', 1)]"/> + domain="['&', ('stage_id.probability', '=', 100), ('stage_id.fold', '=', True)]"/> + domain="['&', ('stage_id.probability', '=', 0), ('stage_id.fold', '=', True)]"/> - + domain="['&', ('stage_id.probability', '=', 100), ('stage_id.on_change', '=', 1)]"/> + domain="['&', ('stage_id.probability', '=', 0), ('stage_id.sequence', '!=', 1)]"/> - diff --cc addons/crm/report/crm_opportunity_report_view.xml index 14ce6c1,9fcd496..2b4805c --- a/addons/crm/report/crm_opportunity_report_view.xml +++ b/addons/crm/report/crm_opportunity_report_view.xml @@@ -60,13 -60,11 +60,11 @@@ - + domain="['&', ('stage_id.probability', '=', 100), ('stage_id.on_change', '=', 1)]"/> + domain="['&', ('stage_id.probability', '=', 0), ('stage_id.sequence', '!=', 1)]"/> - diff --cc addons/mrp/security/ir.model.access.csv index fc3b228,8d6916c..68bf007 --- a/addons/mrp/security/ir.model.access.csv +++ b/addons/mrp/security/ir.model.access.csv @@@ -73,9 -76,7 +73,9 @@@ access_product_pricelist_version_mrp_ma access_product_pricelist_item_mrp_manager,product.pricelist.item mrp_manager,product.model_product_pricelist_item,mrp.group_mrp_manager,1,1,1,1 access_resource_calendar_manufacturinguser,resource.calendar manufacturing.user,resource.model_resource_calendar,mrp.group_mrp_user,1,0,0,0 access_account_journal_mrp_manager,account.journal mrp manager,account.model_account_journal,mrp.group_mrp_manager,1,0,0,0 - access_mrp_property_group,mrp.property.group,model_mrp_property_group,stock.group_stock_manager,1,1,1,1 - access_mrp_property,mrp.property,model_mrp_property,stock.group_stock_manager,1,1,1,1 + access_mrp_property_group_manager,mrp.property.group,model_mrp_property_group,stock.group_stock_manager,1,1,1,1 + access_mrp_property_manager,mrp.property,model_mrp_property,stock.group_stock_manager,1,1,1,1 access_mrp_property_group,mrp.property.group,model_mrp_property_group,base.group_user,1,0,0,0 access_mrp_property,mrp.property,model_mrp_property,base.group_user,1,0,0,0 +access_mrp_bom_invoicing_payment,mrp.bom,model_mrp_bom,account.group_account_invoice,1,0,0,0 +access_mrp_production_invoicing_payment,mrp.production,model_mrp_production,account.group_account_invoice,1,1,1,0 diff --cc addons/payment/views/payment_acquirer.xml index 69e4805,7da63d2..6cf6c7b --- a/addons/payment/views/payment_acquirer.xml +++ b/addons/payment/views/payment_acquirer.xml @@@ -20,7 -20,7 +20,8 @@@ + + diff --cc addons/web/static/src/js/search.js index 148f466,eea5070..3ae52df --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@@ -682,22 -594,321 +682,23 @@@ instance.web.SearchView = instance.web. input_to_focus.$el.focus(); }); }, - - search_view_loaded: function(data) { - var self = this; - this.fields_view = data; + childFocused: function () { + this.$el.addClass('active'); + this.view_id = this.view_id || data.view_id; - if (data.type !== 'search' || - data.arch.tag !== 'search') { - throw new Error(_.str.sprintf( - "Got non-search view after asking for a search view: type %s, arch root %s", - data.type, data.arch.tag)); - } - - return this.drawer_ready - .then(this.proxy('setup_default_query')) - .then(function () { - self.trigger("search_view_loaded", data); - self.ready.resolve(); - }); - }, - setup_default_query: function () { - // Hacky implementation of CustomFilters#facet_for_defaults ensure - // CustomFilters will be ready (and CustomFilters#filters will be - // correctly filled) by the time this method executes. - var custom_filters = this.drawer.custom_filters.filters; - if (!this.options.disable_custom_filters && !_(custom_filters).isEmpty()) { - // Check for any is_default custom filter - var personal_filter = _(custom_filters).find(function (filter) { - return filter.user_id && filter.is_default; - }); - if (personal_filter) { - this.drawer.custom_filters.toggle_filter(personal_filter, true); - return; - } - - var global_filter = _(custom_filters).find(function (filter) { - return !filter.user_id && filter.is_default; - }); - if (global_filter) { - this.drawer.custom_filters.toggle_filter(global_filter, true); - return; - } - } - // No custom filter, or no is_default custom filter, apply view defaults - this.query.reset(_(arguments).compact(), {preventSearch: true}); - }, - /** - * Extract search data from the view's facets. - * - * Result is an object with 4 (own) properties: - * - * errors - * An array of any error generated during data validation and - * extraction, contains the validation error objects - * domains - * Array of domains - * contexts - * Array of contexts - * groupbys - * Array of domains, in groupby order rather than view order - * - * @return {Object} - */ - build_search_data: function () { - var domains = [], contexts = [], groupbys = [], errors = []; - - this.query.each(function (facet) { - var field = facet.get('field'); - try { - var domain = field.get_domain(facet); - if (domain) { - domains.push(domain); - } - var context = field.get_context(facet); - if (context) { - contexts.push(context); - } - var group_by = field.get_groupby(facet); - if (group_by) { - groupbys.push.apply(groupbys, group_by); - } - } catch (e) { - if (e instanceof instance.web.search.Invalid) { - errors.push(e); - } else { - throw e; - } - } - }); - return { - domains: domains, - contexts: contexts, - groupbys: groupbys, - errors: errors - }; - }, - /** - * Performs the search view collection of widget data. - * - * If the collection went well (all fields are valid), then triggers - * :js:func:`instance.web.SearchView.on_search`. - * - * If at least one field failed its validation, triggers - * :js:func:`instance.web.SearchView.on_invalid` instead. - * - * @param [_query] - * @param {Object} [options] - */ - do_search: function (_query, options) { - if (options && options.preventSearch) { - return; - } - var search = this.build_search_data(); - if (!_.isEmpty(search.errors)) { - this.on_invalid(search.errors); - return; - } - this.trigger('search_data', search.domains, search.contexts, search.groupbys); - }, - /** - * Triggered after the SearchView has collected all relevant domains and - * contexts. - * - * It is provided with an Array of domains and an Array of contexts, which - * may or may not be evaluated (each item can be either a valid domain or - * context, or a string to evaluate in order in the sequence) - * - * It is also passed an array of contexts used for group_by (they are in - * the correct order for group_by evaluation, which contexts may not be) - * - * @event - * @param {Array} domains an array of literal domains or domain references - * @param {Array} contexts an array of literal contexts or context refs - * @param {Array} groupbys ordered contexts which may or may not have group_by keys - */ - /** - * Triggered after a validation error in the SearchView fields. - * - * Error objects have three keys: - * * ``field`` is the name of the invalid field - * * ``value`` is the invalid value - * * ``message`` is the (in)validation message provided by the field - * - * @event - * @param {Array} errors a never-empty array of error objects - */ - on_invalid: function (errors) { - this.do_notify(_t("Invalid Search"), _t("triggered from search view")); - this.trigger('invalid_search', errors); - }, - - // The method appendTo is overwrited to be able to insert the drawer anywhere - appendTo: function ($searchview_parent, $searchview_drawer_node) { - var $searchview_drawer_node = $searchview_drawer_node || $searchview_parent; - - return $.when( - this._super($searchview_parent), - this.drawer.appendTo($searchview_drawer_node) - ); - }, - - destroy: function () { - this.drawer.destroy(); - this.getParent().destroy.call(this); - } -}); - -instance.web.SearchViewDrawer = instance.web.Widget.extend({ - template: "SearchViewDrawer", - - init: function(parent, searchview) { - this._super(parent); - this.searchview = searchview; - this.searchview.set_drawer(this); - this.ready = searchview.drawer_ready; - this.controls = []; - this.inputs = []; - }, - - toggle: function (visibility) { - this.$el.toggle(visibility); - var $view_manager_body = this.$el.closest('.oe_view_manager_body'); - if ($view_manager_body.length) { - $view_manager_body.scrollTop(0); - } - }, - - start: function() { - var self = this; - if (this.searchview.headless) return $.when(this._super(), this.searchview.ready); - var filters_ready = this.searchview.fields_view_get - .then(this.proxy('prepare_filters')); - return $.when(this._super(), filters_ready).then(function () { - var defaults = arguments[1][0]; - self.ready.resolve.apply(null, defaults); - }); - }, - prepare_filters: function (data) { - this.make_widgets( - data['arch'].children, - data.fields); - - this.add_common_inputs(); - - // build drawer - var in_drawer = this.select_for_drawer(); - - var $first_col = this.$(".col-md-7"), - $snd_col = this.$(".col-md-5"); - - var add_custom_filters = in_drawer[0].appendTo($first_col), - add_filters = in_drawer[1].appendTo($first_col), - add_rest = $.when.apply(null, _(in_drawer.slice(2)).invoke('appendTo', $snd_col)), - defaults_fetched = $.when.apply(null, _(this.inputs).invoke( - 'facet_for_defaults', this.searchview.defaults)); - - return $.when(defaults_fetched, add_custom_filters, add_filters, add_rest); - }, - /** - * Sets up thingie where all the mess is put? - */ - select_for_drawer: function () { - return _(this.inputs).filter(function (input) { - return input.in_drawer(); - }); - }, - - /** - * Builds a list of widget rows (each row is an array of widgets) - * - * @param {Array} items a list of nodes to convert to widgets - * @param {Object} fields a mapping of field names to (ORM) field attributes - * @param {Object} [group] group to put the new controls in - */ - make_widgets: function (items, fields, group) { - if (!group) { - group = new instance.web.search.Group( - this, 'q', {attrs: {string: _t("Filters")}}); - } - var self = this; - var filters = []; - _.each(items, function (item) { - if (filters.length && item.tag !== 'filter') { - group.push(new instance.web.search.FilterGroup(filters, group)); - filters = []; - } - - switch (item.tag) { - case 'separator': case 'newline': - break; - case 'filter': - filters.push(new instance.web.search.Filter(item, group)); - break; - case 'group': - self.add_separator(); - self.make_widgets(item.children, fields, - new instance.web.search.Group(group, 'w', item)); - self.add_separator(); - break; - case 'field': - var field = this.make_field( - item, fields[item['attrs'].name], group); - group.push(field); - // filters - self.make_widgets(item.children, fields, group); - break; - } - }, this); - - if (filters.length) { - group.push(new instance.web.search.FilterGroup(filters, this)); - } }, - - add_separator: function () { - if (!(_.last(this.inputs) instanceof instance.web.search.Separator)) - new instance.web.search.Separator(this); + childBlurred: function () { + this.$el.val('').removeClass('active').trigger('blur'); + this.autocomplete.close(); }, /** - * Creates a field for the provided field descriptor item (which comes - * from fields_view_get) - * - * @param {Object} item fields_view_get node for the field - * @param {Object} field fields_get result for the field - * @param {Object} [parent] - * @returns instance.web.search.Field + * Call the renderFacets method with the correct arguments. + * This is due to the fact that change events are called with two arguments + * (model, options) while add, reset and remove events are called with + * (collection, model, options) as arguments */ - make_field: function (item, field, parent) { - // M2O combined with selection widget is pointless and broken in search views, - // but has been used in the past for unsupported hacks -> ignore it - if (field.type === "many2one" && item.attrs.widget === "selection"){ - item.attrs.widget = undefined; - } - var obj = instance.web.search.fields.get_any( [item.attrs.widget, field.type]); - if(obj) { - return new (obj) (item, field, parent || this); - } else { - console.group('Unknown field type ' + field.type); - console.error('View node', item); - console.info('View field', field); - console.info('In view', this); - console.groupEnd(); - return null; - } - }, - - add_common_inputs: function() { - // add custom filters to this.inputs - this.custom_filters = new instance.web.search.CustomFilters(this); - // add Filters to this.inputs, need view.controls filled - (new instance.web.search.Filters(this)); - (new instance.web.search.SaveFilter(this, this.custom_filters)); - // add Advanced to this.inputs - (new instance.web.search.Advanced(this)); + renderChangedFacets: function (model, options) { + this.renderFacets(undefined, model, options); }, - }); /** diff --cc addons/web_graph/static/src/js/graph_widget.js index b6ba3a4,13dc558..afb691e --- a/addons/web_graph/static/src/js/graph_widget.js +++ b/addons/web_graph/static/src/js/graph_widget.js @@@ -73,9 -54,9 +73,11 @@@ openerp.web_graph.Graph = openerp.web.W self.$('.graph_options_selection label').last().toggle(result); }); + this.$buttons.find('button').tooltip(); + - return this.model.call('fields_get', []).then(function (f) { + return this.model.call('fields_get', { + context: this.graph_view.dataset.context + }).then(function (f) { self.fields = f; self.fields.__count = {field:'__count', type: 'integer', string:_t('Count')}; self.groupby_fields = self.get_groupby_fields(); diff --cc addons/website/views/res_config.xml index 8762ec7,5b2de47..91fb3aa --- a/addons/website/views/res_config.xml +++ b/addons/website/views/res_config.xml @@@ -13,8 -13,9 +13,9 @@@