[MERGE] forward port of branch saas-5 up to 8dfd5ea
This commit is contained in:
commit
1f57528bc6
|
@ -156,13 +156,13 @@ class base_action_rule(osv.osv):
|
||||||
""" Return a wrapper around `old_create` calling both `old_create` and
|
""" Return a wrapper around `old_create` calling both `old_create` and
|
||||||
`_process`, in that order.
|
`_process`, in that order.
|
||||||
"""
|
"""
|
||||||
def create(cr, uid, vals, context=None):
|
def create(cr, uid, vals, context=None, **kwargs):
|
||||||
# avoid loops or cascading actions
|
# avoid loops or cascading actions
|
||||||
if context and context.get('action'):
|
if context and context.get('action'):
|
||||||
return old_create(cr, uid, vals, context=context)
|
return old_create(cr, uid, vals, context=context)
|
||||||
|
|
||||||
context = dict(context or {}, action=True)
|
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
|
# retrieve the action rules to run on creation
|
||||||
action_dom = [('model', '=', model), ('kind', 'in', ['on_create', 'on_create_or_write'])]
|
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
|
""" Return a wrapper around `old_write` calling both `old_write` and
|
||||||
`_process`, in that order.
|
`_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
|
# avoid loops or cascading actions
|
||||||
if context and context.get('action'):
|
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)
|
context = dict(context or {}, action=True)
|
||||||
ids = [ids] if isinstance(ids, (int, long, str)) else ids
|
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)
|
pre_ids[action] = self._filter(cr, uid, action, action.filter_pre_id, ids, context=context)
|
||||||
|
|
||||||
# execute write
|
# 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
|
# check postconditions, and execute actions on the records that satisfy them
|
||||||
for action in actions:
|
for action in actions:
|
||||||
|
|
|
@ -148,7 +148,7 @@
|
||||||
<record id="mt_job_applicant_new" model="mail.message.subtype">
|
<record id="mt_job_applicant_new" model="mail.message.subtype">
|
||||||
<field name="name">Applicant Created</field>
|
<field name="name">Applicant Created</field>
|
||||||
<field name="res_model">hr.job</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="parent_id" eval="ref('mt_applicant_new')"/>
|
||||||
<field name="relation_field">job_id</field>
|
<field name="relation_field">job_id</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -7,6 +7,9 @@ openerp.hr_timesheet_sheet = function(instance) {
|
||||||
events: {
|
events: {
|
||||||
"click .oe_timesheet_weekly_account a": "go_to",
|
"click .oe_timesheet_weekly_account a": "go_to",
|
||||||
},
|
},
|
||||||
|
ignore_fields: function() {
|
||||||
|
return ['line_id'];
|
||||||
|
},
|
||||||
init: function() {
|
init: function() {
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -323,11 +326,8 @@ openerp.hr_timesheet_sheet = function(instance) {
|
||||||
generate_o2m_value: function() {
|
generate_o2m_value: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var ops = [];
|
var ops = [];
|
||||||
|
var ignored_fields = self.ignore_fields();
|
||||||
_.each(self.accounts, function(account) {
|
_.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(account.days, function(day) {
|
||||||
_.each(day.lines, function(line) {
|
_.each(day.lines, function(line) {
|
||||||
if (line.unit_amount !== 0) {
|
if (line.unit_amount !== 0) {
|
||||||
|
@ -338,12 +338,8 @@ openerp.hr_timesheet_sheet = function(instance) {
|
||||||
tmp[k] = v[0];
|
tmp[k] = v[0];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// we have to remove some keys, because analytic lines are shitty
|
// we remove line_id as the reference to the _inherits field will no longer exists
|
||||||
_.each(_.keys(tmp), function(key) {
|
tmp = _.omit(tmp, ignored_fields);
|
||||||
if (auth_keys[key] === undefined) {
|
|
||||||
tmp[key] = undefined;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ops.push(tmp);
|
ops.push(tmp);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,6 +31,7 @@ class fiche_paye_parser(report_sxw.rml_parse):
|
||||||
def __init__(self, cr, uid, name, context):
|
def __init__(self, cr, uid, name, context):
|
||||||
super(fiche_paye_parser, self).__init__(cr, uid, name, context)
|
super(fiche_paye_parser, self).__init__(cr, uid, name, context)
|
||||||
self.localcontext.update({
|
self.localcontext.update({
|
||||||
|
'lang': "fr_FR",
|
||||||
'get_payslip_lines': self.get_payslip_lines,
|
'get_payslip_lines': self.get_payslip_lines,
|
||||||
'get_total_by_rule_category': self.get_total_by_rule_category,
|
'get_total_by_rule_category': self.get_total_by_rule_category,
|
||||||
'get_employer_line': self.get_employer_line,
|
'get_employer_line': self.get_employer_line,
|
||||||
|
|
|
@ -135,11 +135,11 @@ HDD SH-1</field>
|
||||||
<field name="name">Memory</field>
|
<field name="name">Memory</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="product_attribute_value_1" model="product.attribute.value">
|
<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"/>
|
<field name="attribute_id" ref="product_attribute_1"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="product_attribute_value_2" model="product.attribute.value">
|
<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"/>
|
<field name="attribute_id" ref="product_attribute_1"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
|
@ -3337,6 +3337,7 @@ body.oe_single_form .oe_single_form_container {
|
||||||
background: white;
|
background: white;
|
||||||
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
|
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
z-index: 1800;
|
||||||
}
|
}
|
||||||
.tooltip .tooltip-inner {
|
.tooltip .tooltip-inner {
|
||||||
text-align: left !important;
|
text-align: left !important;
|
||||||
|
|
|
@ -2711,6 +2711,7 @@ body.oe_single_form
|
||||||
background: white
|
background: white
|
||||||
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5)
|
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5)
|
||||||
background-color: transparent
|
background-color: transparent
|
||||||
|
z-index: 1800
|
||||||
.tooltip-inner
|
.tooltip-inner
|
||||||
text-align: left !important
|
text-align: left !important
|
||||||
max-width: 350px
|
max-width: 350px
|
||||||
|
|
|
@ -183,6 +183,7 @@ instance.web.Dialog = instance.web.Widget.extend({
|
||||||
*/
|
*/
|
||||||
close: function(reason) {
|
close: function(reason) {
|
||||||
if (this.dialog_inited && !this.__tmp_dialog_hiding) {
|
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);
|
this.trigger("closing", reason);
|
||||||
if (this.$el.is(":data(bs.modal)")) { // may have been destroyed by closing signal
|
if (this.$el.is(":data(bs.modal)")) { // may have been destroyed by closing signal
|
||||||
this.__tmp_dialog_hiding = true;
|
this.__tmp_dialog_hiding = true;
|
||||||
|
|
|
@ -773,15 +773,18 @@ instance.web.unblockUI = function() {
|
||||||
$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
|
$.fn.tooltip.Constructor.DEFAULTS.placement = 'auto top';
|
||||||
$.fn.tooltip.Constructor.DEFAULTS.html = true;
|
$.fn.tooltip.Constructor.DEFAULTS.html = true;
|
||||||
$.fn.tooltip.Constructor.DEFAULTS.container = 'body';
|
$.fn.tooltip.Constructor.DEFAULTS.container = 'body';
|
||||||
//overwrite bootstrap tooltip method to fix bug when using placement
|
//overwrite bootstrap tooltip method to prevent showing 2 tooltip at the same time
|
||||||
//auto and the parent element does not exist anymore resulting in
|
|
||||||
//an error. This should be remove once bootstrap fix the bug
|
|
||||||
var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
|
var bootstrap_show_function = $.fn.tooltip.Constructor.prototype.show;
|
||||||
$.fn.tooltip.Constructor.prototype.show = function (e) {
|
$.fn.tooltip.Constructor.prototype.show = function () {
|
||||||
if (this.$element.parent().length === 0){
|
$('.tooltip').remove();
|
||||||
return;
|
//the following fix the bug when using placement
|
||||||
}
|
//auto and the parent element does not exist anymore resulting in
|
||||||
return bootstrap_show_function.call(this, e);
|
//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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1869,25 +1869,9 @@ instance.web.form.FormWidget = instance.web.Widget.extend(instance.web.form.Invi
|
||||||
do_attach_tooltip: function(widget, trigger, options) {
|
do_attach_tooltip: function(widget, trigger, options) {
|
||||||
widget = widget || this;
|
widget = widget || this;
|
||||||
trigger = trigger || this.$el;
|
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({
|
options = _.extend({
|
||||||
delay: { show: 500, hide: 0 },
|
delay: { show: 500, hide: 0 },
|
||||||
trigger: 'hover',
|
trigger: 'hover',
|
||||||
container: container,
|
|
||||||
title: function() {
|
title: function() {
|
||||||
var template = widget.template + '.tooltip';
|
var template = widget.template + '.tooltip';
|
||||||
if (!QWeb.has_template(template)) {
|
if (!QWeb.has_template(template)) {
|
||||||
|
@ -2399,6 +2383,7 @@ instance.web.form.KanbanSelection = instance.web.form.FieldChar.extend({
|
||||||
if (li.length) {
|
if (li.length) {
|
||||||
var value = {};
|
var value = {};
|
||||||
value[self.name] = String(li.data('value'));
|
value[self.name] = String(li.data('value'));
|
||||||
|
self.record_id = self.view.datarecord.id;
|
||||||
if (self.record_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));
|
return self.view.dataset._model.call('write', [[self.record_id], value, self.view.dataset.get_context()]).done(self.reload_record.bind(self));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1611,6 +1611,7 @@ instance.web.ListView.Groups = instance.web.Class.extend( /** @lends instance.we
|
||||||
.filter(function (column) { return column.tag === 'field';})
|
.filter(function (column) { return column.tag === 'field';})
|
||||||
.pluck('name').value(),
|
.pluck('name').value(),
|
||||||
function (groups) {
|
function (groups) {
|
||||||
|
self.view.$pager.hide();
|
||||||
$el[0].appendChild(
|
$el[0].appendChild(
|
||||||
self.render_groups(groups));
|
self.render_groups(groups));
|
||||||
if (post_render) { post_render(); }
|
if (post_render) { post_render(); }
|
||||||
|
|
|
@ -617,7 +617,6 @@ instance.web.ViewManager = instance.web.Widget.extend({
|
||||||
var view_promise;
|
var view_promise;
|
||||||
var form = this.views['form'];
|
var form = this.views['form'];
|
||||||
if (!view || (form && form.controller && !form.controller.can_be_discarded())) {
|
if (!view || (form && form.controller && !form.controller.can_be_discarded())) {
|
||||||
self.trigger('switch_mode', view_type, no_store, view_options);
|
|
||||||
return $.Deferred().reject();
|
return $.Deferred().reject();
|
||||||
}
|
}
|
||||||
if (!no_store) {
|
if (!no_store) {
|
||||||
|
|
|
@ -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_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);
|
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);
|
diff_seconds = Math.round((date_stop_day.getTime() - date_start_day.getTime()) / 1000);
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
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);
|
diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -938,10 +938,6 @@ instance.web_kanban.KanbanRecord = instance.web.Widget.extend({
|
||||||
var self = this;
|
var self = this;
|
||||||
this.setup_color_picker();
|
this.setup_color_picker();
|
||||||
this.$el.find('[title]').each(function(){
|
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({
|
$(this).tooltip({
|
||||||
delay: { show: 500, hide: 0},
|
delay: { show: 500, hide: 0},
|
||||||
container: $(this),
|
container: $(this),
|
||||||
|
|
|
@ -198,6 +198,11 @@ class ir_http(orm.AbstractModel):
|
||||||
if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
|
if isinstance(exception.qweb.get('cause'), openerp.exceptions.AccessError):
|
||||||
code = 403
|
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:
|
if code == 500:
|
||||||
logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
|
logger.error("500 Internal Server Error:\n\n%s", values['traceback'])
|
||||||
if 'qweb_exception' in values:
|
if 'qweb_exception' in values:
|
||||||
|
|
|
@ -114,8 +114,8 @@
|
||||||
<t t-foreach="website.menu_id.child_id" t-as="submenu">
|
<t t-foreach="website.menu_id.child_id" t-as="submenu">
|
||||||
<t t-call="website.submenu"/>
|
<t t-call="website.submenu"/>
|
||||||
</t>
|
</t>
|
||||||
<li class="divider" groups="base.group_user,base.group_portal" t-ignore="true"/>
|
<li class="divider" t-ignore="true" t-if="website.user_id != user_id"/>
|
||||||
<li class="dropdown" t-ignore="true" groups="base.group_user,base.group_portal">
|
<li class="dropdown" t-ignore="true" t-if="website.user_id != user_id">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
<b>
|
<b>
|
||||||
<span t-esc="user_id.name"/>
|
<span t-esc="user_id.name"/>
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
element: '.oe_product_cart a:contains("iPod")',
|
element: '.oe_product_cart a:contains("iPod")',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "select ipod 32Go",
|
title: "select ipod 32GB",
|
||||||
waitFor: '#product_detail',
|
waitFor: '#product_detail',
|
||||||
element: 'label:contains(32 Go) input',
|
element: 'label:contains(32 GB) input',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "click on add to cart",
|
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',
|
element: 'form[action="/shop/cart/update"] .btn',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -29,11 +29,11 @@
|
||||||
{
|
{
|
||||||
title: "add one more iPod",
|
title: "add one more iPod",
|
||||||
waitFor: '.my_cart_quantity:contains(2)',
|
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",
|
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',
|
element: '#cart_products tr:contains("Apple In-Ear Headphones") a.js_add_cart_json:first',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -215,7 +215,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
|
||||||
# Set new modules and dependencies
|
# Set new modules and dependencies
|
||||||
modobj.write(cr, SUPERUSER_ID, [module_id], {'state': 'installed', 'latest_version': ver})
|
modobj.write(cr, SUPERUSER_ID, [module_id], {'state': 'installed', 'latest_version': ver})
|
||||||
# Update translations for all installed languages
|
# 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'
|
package.state = 'installed'
|
||||||
for kind in ('init', 'demo', 'update'):
|
for kind in ('init', 'demo', 'update'):
|
||||||
|
|
|
@ -241,8 +241,10 @@ class rml_parse(object):
|
||||||
def _get_lang_dict(self):
|
def _get_lang_dict(self):
|
||||||
pool_lang = self.pool['res.lang']
|
pool_lang = self.pool['res.lang']
|
||||||
lang = self.localcontext.get('lang', 'en_US') or 'en_US'
|
lang = self.localcontext.get('lang', 'en_US') or 'en_US'
|
||||||
lang_ids = pool_lang.search(self.cr,self.uid,[('code','=',lang)])[0]
|
lang_ids = pool_lang.search(self.cr,self.uid,[('code','=',lang)])
|
||||||
lang_obj = pool_lang.browse(self.cr,self.uid,lang_ids)
|
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.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()
|
self.default_lang[lang] = self.lang_dict.copy()
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -156,6 +156,24 @@ def exp_get_progress(id):
|
||||||
exc, tb = a['exception'], a['traceback']
|
exc, tb = a['exception'], a['traceback']
|
||||||
raise Exception, exc, tb
|
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):
|
def exp_drop(db_name):
|
||||||
if db_name not in exp_list(True):
|
if db_name not in exp_list(True):
|
||||||
return False
|
return False
|
||||||
|
@ -164,21 +182,8 @@ def exp_drop(db_name):
|
||||||
|
|
||||||
db = openerp.sql_db.db_connect('postgres')
|
db = openerp.sql_db.db_connect('postgres')
|
||||||
with closing(db.cursor()) as cr:
|
with closing(db.cursor()) as cr:
|
||||||
cr.autocommit(True) # avoid transaction block
|
cr.autocommit(True) # avoid transaction block
|
||||||
# Try to terminate all other connections that might prevent
|
_drop_conn(cr, db_name)
|
||||||
# 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
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cr.execute('DROP DATABASE "%s"' % db_name)
|
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')
|
db = openerp.sql_db.db_connect('postgres')
|
||||||
with closing(db.cursor()) as cr:
|
with closing(db.cursor()) as cr:
|
||||||
cr.autocommit(True) # avoid transaction block
|
cr.autocommit(True) # avoid transaction block
|
||||||
|
_drop_conn(cr, old_name)
|
||||||
try:
|
try:
|
||||||
cr.execute('ALTER DATABASE "%s" RENAME TO "%s"' % (old_name, new_name))
|
cr.execute('ALTER DATABASE "%s" RENAME TO "%s"' % (old_name, new_name))
|
||||||
_logger.info('RENAME DB: %s -> %s', old_name, new_name)
|
_logger.info('RENAME DB: %s -> %s', old_name, new_name)
|
||||||
|
|
|
@ -16,6 +16,8 @@ import unittest2
|
||||||
import urllib2
|
import urllib2
|
||||||
import xmlrpclib
|
import xmlrpclib
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from shutil import rmtree
|
||||||
|
from tempfile import mkdtemp
|
||||||
|
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
|
||||||
|
@ -149,8 +151,10 @@ class HttpCase(TransactionCase):
|
||||||
self.session_id = self.session.sid
|
self.session_id = self.session.sid
|
||||||
self.session.db = DB
|
self.session.db = DB
|
||||||
openerp.http.root.session_store.save(self.session)
|
openerp.http.root.session_store.save(self.session)
|
||||||
|
self.localstorage_path = mkdtemp()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
rmtree(self.localstorage_path)
|
||||||
self.registry.leave_test_mode()
|
self.registry.leave_test_mode()
|
||||||
super(HttpCase, self).tearDown()
|
super(HttpCase, self).tearDown()
|
||||||
|
|
||||||
|
@ -259,7 +263,11 @@ class HttpCase(TransactionCase):
|
||||||
phantomtest = os.path.join(os.path.dirname(__file__), 'phantomtest.js')
|
phantomtest = os.path.join(os.path.dirname(__file__), 'phantomtest.js')
|
||||||
# phantom.args[0] == phantomtest path
|
# phantom.args[0] == phantomtest path
|
||||||
# phantom.args[1] == options
|
# 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)
|
self.phantom_run(cmd, timeout)
|
||||||
|
|
||||||
def phantom_js(self, url_path, code, ready="window", login=None, timeout=60, **kw):
|
def phantom_js(self, url_path, code, ready="window", login=None, timeout=60, **kw):
|
||||||
|
|
Loading…
Reference in New Issue