diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py
index 0684964256f..3b8ed588169 100644
--- a/addons/base/controllers/main.py
+++ b/addons/base/controllers/main.py
@@ -170,25 +170,7 @@ class Session(openerpweb.Controller):
a list of fields to group by, potentially empty (in which case
no group by should be performed)
"""
- context = req.session.eval_contexts(contexts)
- domain = req.session.eval_domains(domains, context)
-
- group_by_sequence = []
- for candidate in (group_by_seq or []):
- ctx = req.session.eval_context(candidate, context)
- group_by = ctx.get('group_by')
- if not group_by:
- continue
- elif isinstance(group_by, basestring):
- group_by_sequence.append(group_by)
- else:
- group_by_sequence.extend(group_by)
-
- return {
- 'context': context,
- 'domain': domain,
- 'group_by': group_by_sequence
- }
+ return _eval_domain_and_context(req, contexts, domains, group_by_seq)
@openerpweb.jsonrequest
def save_session_action(self, req, the_action):
@@ -230,6 +212,26 @@ class Session(openerpweb.Controller):
return None
return saved_actions["actions"].get(key)
+def _eval_domain_and_context(req, contexts, domains, group_by_seq=None):
+ context = req.session.eval_contexts(contexts)
+ domain = req.session.eval_domains(domains, context)
+
+ group_by_sequence = []
+ for candidate in (group_by_seq or []):
+ ctx = req.session.eval_context(candidate, context)
+ group_by = ctx.get('group_by')
+ if not group_by:
+ continue
+ elif isinstance(group_by, basestring):
+ group_by_sequence.append(group_by)
+ else:
+ group_by_sequence.extend(group_by)
+
+ return {
+ 'context': context,
+ 'domain': domain,
+ 'group_by': group_by_sequence
+ }
def load_actions_from_ir_values(req, key, key2, models, meta, context):
Values = req.session.model('ir.values')
@@ -434,7 +436,15 @@ class DataSet(openerpweb.Controller):
return Model.unlink(ids)
@openerpweb.jsonrequest
- def call(self, req, model, method, args):
+ def call(self, req, model, method, args, domain_id=None, context_id=None):
+ domain = args[domain_id] if domain_id and len(args) - 1 >= domain_id else []
+ context = args[context_id] if context_id and len(args) - 1 >= context_id else {}
+ res = _eval_domain_and_context(req, [context], [domain]);
+ if(domain_id and len(args) - 1 >= domain_id):
+ args[context_id] = res["context"]
+ if(context_id and len(args) - 1 >= context_id):
+ args[domain_id] = res["domain"]
+
m = req.session.model(model)
r = getattr(m, method)(*args)
return {'result': r}
diff --git a/addons/base/static/src/js/data.js b/addons/base/static/src/js/data.js
index 76a803fa0ff..581bd217ba9 100644
--- a/addons/base/static/src/js/data.js
+++ b/addons/base/static/src/js/data.js
@@ -320,13 +320,22 @@ openerp.base.DataSet = openerp.base.Controller.extend( /** @lends openerp.base.
args: args || []
}, callback, error_callback);
},
+ call_and_eval: function (method, args, domain_id, context_id, callback, error_callback) {
+ return this.rpc('/base/dataset/call', {
+ model: this.model,
+ method: method,
+ domain_id: domain_id || null,
+ context_id: context_id || null,
+ args: args || []
+ }, callback, error_callback);
+ },
/**
* Arguments:
* name='', args=[], operator='ilike', context=None, limit=100
*/
name_search: function (args, callback, error_callback) {
- return this.call('name_search',
- args,
+ return this.call_and_eval('name_search',
+ args, 1, 3,
callback, error_callback);
},
exec_workflow: function (id, signal, callback) {
@@ -431,6 +440,36 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({
}
});
+openerp.base.CompoundContext = function(source_context) {
+ this.__ref = "compound_context";
+ this.__contexts = [];
+ if (source_context === undefined)
+ return;
+ else if (source_context.__ref === "compound_context")
+ this.__contexts.concat(source_context.__contexts);
+ else
+ this.add(source_context);
+};
+openerp.base.CompoundContext.prototype.add = function(context) {
+ this.__contexts.push(context);
+ return this;
+};
+
+openerp.base.CompoundDomain = function(source_domain) {
+ this.__ref = "compound_domain";
+ this.__domains = [];
+ if (source_domain === undefined)
+ return;
+ else if (source_domain.__ref === "compound_domain")
+ this.__domains.concat(source_domain.__domains);
+ else
+ this.add(source_domain);
+};
+openerp.base.CompoundDomain.prototype.add = function(domain) {
+ this.__domains.push(domain);
+ return this;
+};
+
};
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js
index 8269e9a0cd6..2aa29fac377 100644
--- a/addons/base/static/src/js/form.js
+++ b/addons/base/static/src/js/form.js
@@ -1013,6 +1013,18 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({
});
})(null);
+/**
+ * Builds a new context usable for operations related to fields by merging
+ * the fields'context with the action's context.
+ */
+var build_relation_context = function(relation_field) {
+ var action = relation_field.view.view_manager.action || {};
+ var a_context = action.context || {};
+ var f_context = relation_field.field.context || {};
+ var ctx = new openerp.base.CompoundContext(a_context).add(f_context);
+ return ctx;
+}
+
openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
init: function(view, node) {
this._super(view, node);
@@ -1048,7 +1060,8 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
"type":"ir.actions.act_window",
"view_type":"form",
"view_mode":"form",
- "target":"new"
+ "target":"new",
+ "context": build_relation_context(self)
});
};
var cmenu = this.$menu_btn.contextMenu(this.cm_id, {'leftClickToo': true,
@@ -1125,23 +1138,26 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, []);
- dataset.name_search([search_val, [], 'ilike', {}, this.limit + 1], function(data) {
+ dataset.name_search([search_val, self.field.domain || [], 'ilike',
+ build_relation_context(self), this.limit + 1], function(data) {
self.last_search = data.result;
// possible selections for the m2o
var values = _.map(data.result, function(x) {
return {label: $('').text(x[1]).html(), name:x[1], id:x[0]};
});
- // additional selections, actions that open popup
+ // search more... if more results that max
if (values.length > self.limit) {
values = values.slice(0, self.limit);
values.push({label: " Search More...", action: function() {
- dataset.name_search([search_val, [], 'ilike', {}, false], function(data) {
+ dataset.name_search([search_val, self.field.domain || [], 'ilike',
+ build_relation_context(self), false], function(data) {
self._change_int_value(null);
self._search_create_popup("search", data.result);
});
}});
}
+ // quick create
var raw_result = _(data.result).map(function(x) {return x[1];})
if (search_val.length > 0 &&
!_.include(raw_result, search_val) &&
@@ -1151,6 +1167,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
self._quick_create(search_val);
}});
}
+ // create...
values.push({label: " Create and Edit...", action: function() {
self._change_int_value(null);
self._search_create_popup("form");
@@ -1162,7 +1179,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({
_quick_create: function(name) {
var self = this;
var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, []);
- dataset.call("name_create", [name, {}], function(data) {
+ dataset.call("name_create", [name, build_relation_context(self)], function(data) {
self._change_int_ext_value(data.result);
}, function(a, b) {
self._change_int_value(null);
@@ -1401,8 +1418,10 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
* - disable_multiple_selection
* - alternative_form_view
*/
- select_element: function(model, options) {
+ select_element: function(model, options, domain, context) {
this.model = model;
+ this.domain = domain || [];
+ this.context = context || {};
this.options = options || {};
this.initial_ids = this.options.initial_ids;
jQuery(this.render()).dialog({title: '',
@@ -1485,7 +1504,6 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({
this.view_form = new openerp.base.FormView(null, this.session,
this.element_id + "_view_form", this.dataset, false);
if (this.options.alternative_form_view) {
- debugger;
this.view_form.set_embedded_view(this.options.alternative_form_view);
}
this.view_form.start();
diff --git a/openerpweb/nonliterals.py b/openerpweb/nonliterals.py
index 1584628f777..38c94e6d230 100644
--- a/openerpweb/nonliterals.py
+++ b/openerpweb/nonliterals.py
@@ -27,6 +27,16 @@ class NonLiteralEncoder(simplejson.encoder.JSONEncoder):
'__ref': 'context',
'__id': object.key
}
+ elif isinstance(object, CompoundDomain):
+ return {
+ '__ref': 'compound_domain',
+ '__domains': [self.default(el) for el in object.domains]
+ }
+ elif isinstance(object, CompoundContext):
+ return {
+ '__ref': 'compound_context',
+ '__contexts': [self.default(el) for el in object.contexts]
+ }
return super(NonLiteralEncoder, self).default(object)
def non_literal_decoder(dct):
@@ -47,6 +57,16 @@ def non_literal_decoder(dct):
if 'own_values' in dct:
context.own = dct['own_values']
return context
+ elif dct["__ref"] == "compound_domain":
+ cdomain = CompoundDomain()
+ for el in dct["__domains"]:
+ cdomain.domains.append(non_literal_decoder(el))
+ return cdomain
+ elif dct["__ref"] == "compound_context":
+ ccontext = CompoundContext()
+ for el in dct["__contexts"]:
+ ccontext.contexts.append(non_literal_decoder(el))
+ return ccontext
return dct
class Domain(object):
@@ -138,3 +158,59 @@ class Context(object):
ctx.update(self.own)
return eval(self.get_context_string(),
ctx)
+
+class CompoundDomain:
+ def __init__(self):
+ self.domains = []
+ self.session = None
+
+ def evaluate(self, context=None):
+ final_domain = []
+ for domain in self.domains:
+ if not isinstance(domain, (list, Domain, CompoundDomain)):
+ raise TypeError("Domain %r is not a list or a nonliteral Domain",
+ domain)
+
+ if isinstance(domain, list):
+ final_domain.extend(domain)
+ break
+
+ ctx = dict(context or {})
+ ctx['context'] = ctx
+
+ domain.session = self.session
+ domain.extend(domain.evaluate(ctx))
+ return final_domain
+
+ def add(self, domain):
+ self.domains.append(domain)
+ return self
+
+class CompoundContext:
+ def __init__(self):
+ self.contexts = []
+ self.session = None
+
+ def evaluate(self, context=None):
+ ctx = dict(context or {})
+ final_context = {}
+ for context_to_eval in self.contexts:
+ if not isinstance(context_to_eval, (dict, Context, CompoundContext)):
+ raise TypeError("Context %r is not a dict or a nonliteral Context",
+ context_to_eval)
+
+ if isinstance(context_to_eval, dict):
+ final_context.update(context_to_eval)
+ break
+
+ ctx.update(final_context)
+ ctx["context"] = ctx
+
+ context_to_eval.session = self.session
+ final_context.update(context_to_eval.evaluate(ctx))
+ return final_context
+
+ def add(self, context):
+ self.contexts.append(context)
+ return self
+
diff --git a/openerpweb/openerpweb.py b/openerpweb/openerpweb.py
index 5ef4369dbb5..2ee59779cb3 100644
--- a/openerpweb/openerpweb.py
+++ b/openerpweb/openerpweb.py
@@ -194,7 +194,7 @@ class OpenERPSession(object):
:raises: ``TypeError`` if ``context_to_eval`` is neither a dict nor
a Context
"""
- if not isinstance(context_to_eval, (dict, nonliterals.Domain)):
+ if not isinstance(context_to_eval, (dict, nonliterals.Context, nonliterals.CompoundContext)):
raise TypeError("Context %r is not a dict or a nonliteral Context",
context_to_eval)
@@ -250,7 +250,7 @@ class OpenERPSession(object):
:raises: ``TypeError`` if ``domain`` is neither a list nor a Domain
"""
- if not isinstance(domain, (list, nonliterals.Domain)):
+ if not isinstance(domain, (list, nonliterals.Domain, nonliterals.CompoundDomain)):
raise TypeError("Domain %r is not a list or a nonliteral Domain",
domain)