[MERGE] forward port of branch saas-5 up to 8dfd5ea

This commit is contained in:
Christophe Simonis 2014-06-27 16:14:40 +02:00
commit 1f57528bc6
21 changed files with 84 additions and 75 deletions

View File

@ -156,13 +156,13 @@ class base_action_rule(osv.osv):
""" Return a wrapper around `old_create` calling both `old_create` and
`_process`, in that order.
"""
def create(cr, uid, vals, context=None):
def create(cr, uid, vals, context=None, **kwargs):
# avoid loops or cascading actions
if context and context.get('action'):
return old_create(cr, uid, vals, context=context)
context = dict(context or {}, action=True)
new_id = old_create(cr, uid, vals, context=context)
new_id = old_create(cr, uid, vals, context=context, **kwargs)
# retrieve the action rules to run on creation
action_dom = [('model', '=', model), ('kind', 'in', ['on_create', 'on_create_or_write'])]
@ -180,10 +180,10 @@ class base_action_rule(osv.osv):
""" Return a wrapper around `old_write` calling both `old_write` and
`_process`, in that order.
"""
def write(cr, uid, ids, vals, context=None):
def write(cr, uid, ids, vals, context=None, **kwargs):
# avoid loops or cascading actions
if context and context.get('action'):
return old_write(cr, uid, ids, vals, context=context)
return old_write(cr, uid, ids, vals, context=context, **kwargs)
context = dict(context or {}, action=True)
ids = [ids] if isinstance(ids, (int, long, str)) else ids
@ -199,7 +199,7 @@ class base_action_rule(osv.osv):
pre_ids[action] = self._filter(cr, uid, action, action.filter_pre_id, ids, context=context)
# execute write
old_write(cr, uid, ids, vals, context=context)
old_write(cr, uid, ids, vals, context=context, **kwargs)
# check postconditions, and execute actions on the records that satisfy them
for action in actions:

View File

@ -148,7 +148,7 @@
<record id="mt_job_applicant_new" model="mail.message.subtype">
<field name="name">Applicant Created</field>
<field name="res_model">hr.job</field>
<field name="default" eval="False"/>
<field name="default" eval="True"/>
<field name="parent_id" eval="ref('mt_applicant_new')"/>
<field name="relation_field">job_id</field>
</record>

View File

@ -7,6 +7,9 @@ openerp.hr_timesheet_sheet = function(instance) {
events: {
"click .oe_timesheet_weekly_account a": "go_to",
},
ignore_fields: function() {
return ['line_id'];
},
init: function() {
this._super.apply(this, arguments);
var self = this;
@ -323,11 +326,8 @@ openerp.hr_timesheet_sheet = function(instance) {
generate_o2m_value: function() {
var self = this;
var ops = [];
var ignored_fields = self.ignore_fields();
_.each(self.accounts, function(account) {
var auth_keys = _.extend(_.clone(account.account_defaults), {
name: true, amount:true, unit_amount: true, date: true, account_id:true,
});
_.each(account.days, function(day) {
_.each(day.lines, function(line) {
if (line.unit_amount !== 0) {
@ -338,12 +338,8 @@ openerp.hr_timesheet_sheet = function(instance) {
tmp[k] = v[0];
}
});
// we have to remove some keys, because analytic lines are shitty
_.each(_.keys(tmp), function(key) {
if (auth_keys[key] === undefined) {
tmp[key] = undefined;
}
});
// we remove line_id as the reference to the _inherits field will no longer exists
tmp = _.omit(tmp, ignored_fields);
ops.push(tmp);
}
});

View File

@ -31,6 +31,7 @@ class fiche_paye_parser(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
super(fiche_paye_parser, self).__init__(cr, uid, name, context)
self.localcontext.update({
'lang': "fr_FR",
'get_payslip_lines': self.get_payslip_lines,
'get_total_by_rule_category': self.get_total_by_rule_category,
'get_employer_line': self.get_employer_line,

View File

@ -135,11 +135,11 @@ HDD SH-1</field>
<field name="name">Memory</field>
</record>
<record id="product_attribute_value_1" model="product.attribute.value">
<field name="name">16 Go</field>
<field name="name">16 GB</field>
<field name="attribute_id" ref="product_attribute_1"/>
</record>
<record id="product_attribute_value_2" model="product.attribute.value">
<field name="name">32 Go</field>
<field name="name">32 GB</field>
<field name="attribute_id" ref="product_attribute_1"/>
</record>

View File

@ -3337,6 +3337,7 @@ body.oe_single_form .oe_single_form_container {
background: white;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
background-color: transparent;
z-index: 1800;
}
.tooltip .tooltip-inner {
text-align: left !important;

View File

@ -2711,6 +2711,7 @@ body.oe_single_form
background: white
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5)
background-color: transparent
z-index: 1800
.tooltip-inner
text-align: left !important
max-width: 350px

View File

@ -183,6 +183,7 @@ instance.web.Dialog = instance.web.Widget.extend({
*/
close: function(reason) {
if (this.dialog_inited && !this.__tmp_dialog_hiding) {
$('.tooltip').remove(); //remove open tooltip if any to prevent them staying when modal has disappeared
this.trigger("closing", reason);
if (this.$el.is(":data(bs.modal)")) { // may have been destroyed by closing signal
this.__tmp_dialog_hiding = true;

View File

@ -773,15 +773,18 @@ instance.web.unblockUI = function() {
$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
$.fn.tooltip.Constructor.DEFAULTS.html = true;
$.fn.tooltip.Constructor.DEFAULTS.container = 'body';
//overwrite bootstrap tooltip method to fix bug when using placement
//auto and the parent element does not exist anymore resulting in
//an error. This should be remove once bootstrap fix the bug
//overwrite bootstrap tooltip method to prevent showing 2 tooltip at the same time
var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
$.fn.tooltip.Constructor.prototype.show = function (e) {
if (this.$element.parent().length === 0){
return;
}
return bootstrap_show_function.call(this, e);
$.fn.tooltip.Constructor.prototype.show = function () {
$('.tooltip').remove();
//the following fix the bug when using placement
//auto and the parent element does not exist anymore resulting in
//an error. This should be remove once we updade bootstrap to a version that fix the bug
//edit: bug has been fixed here : https://github.com/twbs/bootstrap/pull/13752
var e = $.Event('show.bs.' + this.type);
var inDom = $.contains(document.documentElement, this.$element[0]);
if (e.isDefaultPrevented() || !inDom) return;
return bootstrap_show_function.call(this);
};
/**

View File

@ -1869,25 +1869,9 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
do_attach_tooltip: function(widget, trigger, options) {
widget = widget || this;
trigger = trigger || this.$el;
var container = 'body';
/*TODO: need to be refactor
in the case we can find the view form in the parent,
attach the element to it (to prevent tooltip to keep showing
when switching view) or if we have a modal currently showing,
attach tooltip to the modal to prevent the tooltip to show in the body in the
case we close the modal too fast*/
if ($(trigger).parents('.oe_view_manager_view_form').length > 0){
container = $(trigger).parents('.oe_view_manager_view_form');
}
else {
if (window.$('.modal.in').length>0){
container = window.$('.modal.in:last()');
}
}
options = _.extend({
delay: { show: 500, hide: 0 },
trigger: 'hover',
container: container,
title: function() {
var template = widget.template + '.tooltip';
if (!QWeb.has_template(template)) {
@ -2399,6 +2383,7 @@ instance.web.form.KanbanSelection = instance.web.form.FieldChar.extend({
if (li.length) {
var value = {};
value[self.name] = String(li.data('value'));
self.record_id = self.view.datarecord.id;
if (self.record_id) {
return self.view.dataset._model.call('write', [[self.record_id], value, self.view.dataset.get_context()]).done(self.reload_record.bind(self));
} else {

View File

@ -1611,6 +1611,7 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
.filter(function (column) { return column.tag === 'field';})
.pluck('name').value(),
function (groups) {
self.view.$pager.hide();
$el[0].appendChild(
self.render_groups(groups));
if (post_render) { post_render(); }

View File

@ -617,7 +617,6 @@ instance.web.ViewManager = instance.web.Widget.extend({
var view_promise;
var form = this.views['form'];
if (!view || (form && form.controller && !form.controller.can_be_discarded())) {
self.trigger('switch_mode', view_type, no_store, view_options);
return $.Deferred().reject();
}
if (!no_store) {

View File

@ -610,13 +610,17 @@ openerp.web_calendar = function(instance) {
date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7);
date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19);
}
data[this.date_start] = instance.web.parse_value(date_start_day, this.fields[this.date_start]);
if (this.date_stop) {
data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]);
}
diff_seconds = Math.round((date_stop_day.getTime() - date_start_day.getTime()) / 1000);
}
else {
data[this.date_start] = event.start;
data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]);
if (this.date_stop) {
data[this.date_stop] = event_end;
data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]);
}
diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000);
}

View File

@ -938,10 +938,6 @@ instance.web_kanban.KanbanRecord = instance.web.Widget.extend({
var self = this;
this.setup_color_picker();
this.$el.find('[title]').each(function(){
//in case of kanban, attach tooltip to the element itself
//otherwise it might stay on screen when kanban view reload
//since default container is body.
//(when clicking on ready for next stage for example)
$(this).tooltip({
delay: { show: 500, hide: 0},
container: $(this),

View File

@ -198,6 +198,11 @@ class ir_http(orm.AbstractModel):
if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
code = 403
if isinstance(exception, werkzeug.exceptions.HTTPException) and code is None:
# Hand-crafted HTTPException likely coming from abort(),
# usually for a redirect response -> return it directly
return exception
if code == 500:
logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
if 'qweb_exception' in values:

View File

@ -114,8 +114,8 @@
<t t-foreach="website.menu_id.child_id" t-as="submenu">
<t t-call="website.submenu"/>
</t>
<li class="divider" groups="base.group_user,base.group_portal" t-ignore="true"/>
<li class="dropdown" t-ignore="true" groups="base.group_user,base.group_portal">
<li class="divider" t-ignore="true" t-if="website.user_id != user_id"/>
<li class="dropdown" t-ignore="true" t-if="website.user_id != user_id">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<b>
<span t-esc="user_id.name"/>

View File

@ -12,13 +12,13 @@
element: '.oe_product_cart a:contains("iPod")',
},
{
title: "select ipod 32Go",
title: "select ipod 32GB",
waitFor: '#product_detail',
element: 'label:contains(32 Go) input',
element: 'label:contains(32 GB) input',
},
{
title: "click on add to cart",
waitFor: 'label:contains(32 Go) input[checked]',
waitFor: 'label:contains(32 GB) input[checked]',
element: 'form[action="/shop/cart/update"] .btn',
},
{
@ -29,11 +29,11 @@
{
title: "add one more iPod",
waitFor: '.my_cart_quantity:contains(2)',
element: '#cart_products tr:contains("32 Go") a.js_add_cart_json:eq(1)',
element: '#cart_products tr:contains("32 GB") a.js_add_cart_json:eq(1)',
},
{
title: "remove Headphones",
waitFor: '#cart_products tr:contains("32 Go") input.js_quantity[value=2]',
waitFor: '#cart_products tr:contains("32 GB") input.js_quantity[value=2]',
element: '#cart_products tr:contains("Apple In-Ear Headphones") a.js_add_cart_json:first',
},
{

View File

@ -215,7 +215,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
# Set new modules and dependencies
modobj.write(cr, SUPERUSER_ID, [module_id], {'state': 'installed', 'latest_version': ver})
# Update translations for all installed languages
modobj.update_translations(cr, SUPERUSER_ID, [module_id], None)
modobj.update_translations(cr, SUPERUSER_ID, [module_id], None, {'overwrite': openerp.tools.config["overwrite_existing_translations"]})
package.state = 'installed'
for kind in ('init', 'demo', 'update'):

View File

@ -241,8 +241,10 @@ class rml_parse(object):
def _get_lang_dict(self):
pool_lang = self.pool['res.lang']
lang = self.localcontext.get('lang', 'en_US') or 'en_US'
lang_ids = pool_lang.search(self.cr,self.uid,[('code','=',lang)])[0]
lang_obj = pool_lang.browse(self.cr,self.uid,lang_ids)
lang_ids = pool_lang.search(self.cr,self.uid,[('code','=',lang)])
if not lang_ids:
lang_ids = pool_lang.search(self.cr,self.uid,[('code','=','en_US')])
lang_obj = pool_lang.browse(self.cr,self.uid,lang_ids[0])
self.lang_dict.update({'lang_obj':lang_obj,'date_format':lang_obj.date_format,'time_format':lang_obj.time_format})
self.default_lang[lang] = self.lang_dict.copy()
return True

View File

@ -156,6 +156,24 @@ def exp_get_progress(id):
exc, tb = a['exception'], a['traceback']
raise Exception, exc, tb
def _drop_conn(cr, db_name):
# Try to terminate all other connections that might prevent
# dropping the database
try:
# PostgreSQL 9.2 renamed pg_stat_activity.procpid to pid:
# http://www.postgresql.org/docs/9.2/static/release-9-2.html#AEN110389
pid_col = 'pid' if cr._cnx.server_version >= 90200 else 'procpid'
cr.execute("""SELECT pg_terminate_backend(%(pid_col)s)
FROM pg_stat_activity
WHERE datname = %%s AND
%(pid_col)s != pg_backend_pid()""" % {'pid_col': pid_col},
(db_name,))
except Exception:
pass
def exp_drop(db_name):
if db_name not in exp_list(True):
return False
@ -164,21 +182,8 @@ def exp_drop(db_name):
db = openerp.sql_db.db_connect('postgres')
with closing(db.cursor()) as cr:
cr.autocommit(True) # avoid transaction block
# Try to terminate all other connections that might prevent
# dropping the database
try:
# PostgreSQL 9.2 renamed pg_stat_activity.procpid to pid:
# http://www.postgresql.org/docs/9.2/static/release-9-2.html#AEN110389
pid_col = 'pid' if cr._cnx.server_version >= 90200 else 'procpid'
cr.execute("""SELECT pg_terminate_backend(%(pid_col)s)
FROM pg_stat_activity
WHERE datname = %%s AND
%(pid_col)s != pg_backend_pid()""" % {'pid_col': pid_col},
(db_name,))
except Exception:
pass
cr.autocommit(True) # avoid transaction block
_drop_conn(cr, db_name)
try:
cr.execute('DROP DATABASE "%s"' % db_name)
@ -335,6 +340,7 @@ def exp_rename(old_name, new_name):
db = openerp.sql_db.db_connect('postgres')
with closing(db.cursor()) as cr:
cr.autocommit(True) # avoid transaction block
_drop_conn(cr, old_name)
try:
cr.execute('ALTER DATABASE "%s" RENAME TO "%s"' % (old_name, new_name))
_logger.info('RENAME DB: %s -> %s', old_name, new_name)

View File

@ -16,6 +16,8 @@ import unittest2
import urllib2
import xmlrpclib
from datetime import datetime, timedelta
from shutil import rmtree
from tempfile import mkdtemp
import werkzeug
@ -149,8 +151,10 @@ class HttpCase(TransactionCase):
self.session_id = self.session.sid
self.session.db = DB
openerp.http.root.session_store.save(self.session)
self.localstorage_path = mkdtemp()
def tearDown(self):
rmtree(self.localstorage_path)
self.registry.leave_test_mode()
super(HttpCase, self).tearDown()
@ -259,7 +263,11 @@ class HttpCase(TransactionCase):
phantomtest = os.path.join(os.path.dirname(__file__), 'phantomtest.js')
# phantom.args[0] == phantomtest path
# phantom.args[1] == options
cmd = ['phantomjs', jsfile, phantomtest, json.dumps(options)]
cmd = [
'phantomjs',
'--local-storage-path', self.localstorage_path,
jsfile, phantomtest, json.dumps(options)
]
self.phantom_run(cmd, timeout)
def phantom_js(self, url_path, code, ready="window", login=None, timeout=60, **kw):