[MERGE] forward port of branch saas-3 up to 75884c3
This commit is contained in:
commit
1f20f61ab4
|
@ -1,2 +0,0 @@
|
|||
.*
|
||||
**/node_modules
|
|
@ -128,8 +128,7 @@ class sale_order(osv.osv):
|
|||
sale_clause = ''
|
||||
no_invoiced = False
|
||||
for arg in args:
|
||||
if arg[1] == '=':
|
||||
if arg[2]:
|
||||
if (arg[1] == '=' and arg[2]) or (arg[1] == '!=' and not arg[2]):
|
||||
clause += 'AND inv.state = \'paid\''
|
||||
else:
|
||||
clause += 'AND inv.state != \'cancel\' AND sale.state != \'cancel\' AND inv.state <> \'paid\' AND rel.order_id = sale.id '
|
||||
|
|
|
@ -2611,11 +2611,11 @@
|
|||
.openerp .oe_list_editable .oe_list_content td.oe_list_field_cell {
|
||||
padding: 4px 6px 3px;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) {
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell {
|
||||
color: transparent;
|
||||
text-shadow: none;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell:not(.oe_readonly) * {
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_edition .oe_list_field_cell * {
|
||||
visibility: hidden;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_m2o_drop_down_button {
|
||||
|
@ -2631,6 +2631,13 @@
|
|||
min-width: 0;
|
||||
max-width: none;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_list_field_handle {
|
||||
color: transparent;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_readonly {
|
||||
padding: 4px 6px 3px;
|
||||
text-align: left;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field textarea {
|
||||
height: 27px;
|
||||
-moz-border-radius: 0;
|
||||
|
@ -2642,9 +2649,14 @@
|
|||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field textarea, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field select {
|
||||
min-width: 0;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_float input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_view_integer input {
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_float.oe_readonly, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_view_integer.oe_readonly {
|
||||
padding: 6px 0px 0px;
|
||||
text-align: right;
|
||||
max-width: 100px;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_float input, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_view_integer input {
|
||||
width: 100% !important;
|
||||
text-align: right;
|
||||
}
|
||||
.openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_datetime input.oe_datepicker_master, .openerp .oe_list.oe_list_editable.oe_editing .oe_form_field.oe_form_field_date input.oe_datepicker_master {
|
||||
width: 100% !important;
|
||||
|
|
|
@ -2117,7 +2117,7 @@ $sheet-padding: 16px
|
|||
.oe_list_editable .oe_list_content td.oe_list_field_cell
|
||||
padding: 4px 6px 3px
|
||||
.oe_list.oe_list_editable.oe_editing
|
||||
.oe_edition .oe_list_field_cell:not(.oe_readonly)
|
||||
.oe_edition .oe_list_field_cell
|
||||
*
|
||||
visibility: hidden
|
||||
color: transparent
|
||||
|
@ -2129,6 +2129,11 @@ $sheet-padding: 16px
|
|||
.oe_input_icon
|
||||
margin-top: 5px
|
||||
.oe_form_field
|
||||
&.oe_list_field_handle
|
||||
color: transparent
|
||||
&.oe_readonly
|
||||
padding: 4px 6px 3px
|
||||
text-align: left
|
||||
min-width: 0
|
||||
max-width: none
|
||||
input, textarea
|
||||
|
@ -2139,9 +2144,13 @@ $sheet-padding: 16px
|
|||
input, textarea, select
|
||||
min-width: 0
|
||||
&.oe_form_field_float,&.oe_form_view_integer
|
||||
input
|
||||
&.oe_readonly
|
||||
padding: 6px 0px 0px
|
||||
text-align: right
|
||||
max-width: 100px
|
||||
input
|
||||
width: 100% !important
|
||||
text-align: right
|
||||
&.oe_form_field_datetime,&.oe_form_field_date
|
||||
input.oe_datepicker_master
|
||||
width: 100% !important
|
||||
|
|
|
@ -2695,8 +2695,10 @@ instance.web.form.FieldDatetime = instance.web.form.AbstractField.extend(instanc
|
|||
},
|
||||
set_dimensions: function (height, width) {
|
||||
this._super(height, width);
|
||||
if (!this.get("effective_readonly")) {
|
||||
this.datewidget.$input.css('height', height);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
instance.web.form.FieldDate = instance.web.form.FieldDatetime.extend({
|
||||
|
@ -3386,6 +3388,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
this.floating = false;
|
||||
this.current_display = null;
|
||||
this.is_started = false;
|
||||
this.ignore_focusout = false;
|
||||
},
|
||||
reinit_value: function(val) {
|
||||
this.internal_set_value(val);
|
||||
|
@ -3517,6 +3520,7 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
var ed_delay = 200;
|
||||
var ed_duration = 15000;
|
||||
var anyoneLoosesFocus = function (e) {
|
||||
if (self.ignore_focusout) { return; }
|
||||
var used = false;
|
||||
if (self.floating) {
|
||||
if (self.last_search.length > 0) {
|
||||
|
@ -3718,10 +3722,16 @@ instance.web.form.FieldMany2One = instance.web.form.AbstractField.extend(instanc
|
|||
_search_create_popup: function() {
|
||||
this.no_ed = true;
|
||||
this.ed_def.reject();
|
||||
return instance.web.form.CompletionFieldMixin._search_create_popup.apply(this, arguments);
|
||||
this.ignore_focusout = true;
|
||||
this.reinit_value(false);
|
||||
var res = instance.web.form.CompletionFieldMixin._search_create_popup.apply(this, arguments);
|
||||
this.ignore_focusout = false;
|
||||
this.no_ed = false;
|
||||
return res;
|
||||
},
|
||||
set_dimensions: function (height, width) {
|
||||
this._super(height, width);
|
||||
if (!this.get("effective_readonly") && this.$input)
|
||||
this.$input.css('height', height);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -285,10 +285,8 @@
|
|||
if (!this.editor.is_editing()) { return; }
|
||||
for(var i=0, len=this.fields_for_resize.length; i<len; ++i) {
|
||||
var item = this.fields_for_resize[i];
|
||||
if (!item.field.get('effective_invisible')) {
|
||||
this.resize_field(item.field, item.cell);
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Resizes a field's root element based on the corresponding cell of
|
||||
|
@ -306,6 +304,11 @@
|
|||
at: 'left top',
|
||||
of: $cell
|
||||
});
|
||||
if (field.get('effective_readonly')) {
|
||||
field.$el.addClass('oe_readonly');
|
||||
}
|
||||
if(field.widget == "handle")
|
||||
field.$el.addClass('oe_list_field_handle');
|
||||
},
|
||||
/**
|
||||
* @return {jQuery.Deferred}
|
||||
|
@ -451,13 +454,7 @@
|
|||
setup_events: function () {
|
||||
var self = this;
|
||||
_.each(this.editor.form.fields, function(field, field_name) {
|
||||
var set_invisible = function() {
|
||||
field.set({'force_invisible': field.get('effective_readonly')});
|
||||
};
|
||||
field.on("change:effective_readonly", self, set_invisible);
|
||||
set_invisible();
|
||||
field.on('change:effective_invisible', self, function () {
|
||||
if (field.get('effective_invisible')) { return; }
|
||||
field.on("change:effective_readonly", self, function(){
|
||||
var item = _(self.fields_for_resize).find(function (item) {
|
||||
return item.field === field;
|
||||
});
|
||||
|
|
|
@ -76,6 +76,7 @@ class ir_http(osv.AbstractModel):
|
|||
request.uid = request.session.uid
|
||||
|
||||
def _authenticate(self, auth_method='user'):
|
||||
try:
|
||||
if request.session.uid:
|
||||
try:
|
||||
request.session.check_security()
|
||||
|
@ -87,6 +88,11 @@ class ir_http(osv.AbstractModel):
|
|||
# let them bubble up
|
||||
request.session.logout()
|
||||
getattr(self, "_auth_method_%s" % auth_method)()
|
||||
except (openerp.exceptions.AccessDenied, openerp.http.SessionExpiredException):
|
||||
raise
|
||||
except Exception:
|
||||
_logger.exception("Exception during request Authentication.")
|
||||
raise openerp.exceptions.AccessDenied()
|
||||
return auth_method
|
||||
|
||||
def _handle_exception(self, exception):
|
||||
|
|
|
@ -487,6 +487,7 @@ class module(osv.osv):
|
|||
'params': {'menu_id': menu_ids and menu_ids[0] or False}
|
||||
}
|
||||
|
||||
#TODO remove me in master, not called anymore
|
||||
def button_immediate_uninstall(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Uninstall the selected module(s) immediately and fully,
|
||||
|
|
|
@ -82,8 +82,7 @@
|
|||
<div>
|
||||
<button name="button_immediate_install" states="uninstalled" string="Install" type="object" class="oe_highlight"/>
|
||||
<button name="button_immediate_upgrade" states="installed" string="Upgrade" type="object" class="oe_highlight"/>
|
||||
<button name="button_immediate_uninstall" states="installed" string="Uninstall" type="object"
|
||||
confirm="Do you confirm the uninstallation of this module? This will permanently erase all data currently stored by the module!"/>
|
||||
<button name="button_uninstall" states="installed" string="Uninstall" type="object"/>
|
||||
<button name="button_uninstall_cancel" states="to remove" string="Cancel Uninstall" type="object"/>
|
||||
<button name="button_upgrade_cancel" states="to upgrade" string="Cancel Upgrade" type="object"/>
|
||||
<button name="button_install_cancel" states="to install" string="Cancel Install" type="object"/>
|
||||
|
|
|
@ -68,6 +68,20 @@ class base_module_upgrade(osv.osv_memory):
|
|||
res = mod_obj.read(cr, uid, ids, ['name','state'], context)
|
||||
return {'module_info': '\n'.join(map(lambda x: x['name']+' : '+x['state'], res))}
|
||||
|
||||
def upgrade_module_cancel(self, cr, uid, ids, context=None):
|
||||
mod_obj = self.pool.get('ir.module.module')
|
||||
to_installed_ids = mod_obj.search(cr, uid, [
|
||||
('state', 'in', ['to upgrade', 'to remove'])])
|
||||
if to_installed_ids:
|
||||
mod_obj.write(cr, uid, to_installed_ids, {'state': 'installed'}, context=context)
|
||||
|
||||
to_uninstalled_ids = mod_obj.search(cr, uid, [
|
||||
('state', '=', 'to install')])
|
||||
if to_uninstalled_ids:
|
||||
mod_obj.write(cr, uid, to_uninstalled_ids, {'state': 'uninstalled'}, context=context)
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
def upgrade_module(self, cr, uid, ids, context=None):
|
||||
ir_module = self.pool.get('ir.module.module')
|
||||
|
||||
|
|
|
@ -7,14 +7,15 @@
|
|||
<field name="model">base.module.upgrade</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="System Update" version="7.0">
|
||||
<div><label string="Your system will be updated."/></div>
|
||||
<div><label string="Note that this operation might take a few minutes."/></div>
|
||||
<separator string="Modules to Update"/>
|
||||
<p>This module will trigger the uninstallation of below modules.</p>
|
||||
<p><strong>This operation will permanently erase all data currently stored by the modules!</strong></p>
|
||||
<p>If you wish to cancel the process, press the cancel button below</p>
|
||||
<separator string="Impacted Modules"/>
|
||||
<field name="module_info"/>
|
||||
<footer>
|
||||
<button name="upgrade_module" string="Update" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel"/>
|
||||
<button string="Cancel" class="oe_link" name="upgrade_module_cancel" type="object"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -28,6 +28,7 @@ from openerp.osv import osv, fields
|
|||
from openerp.tools import ustr
|
||||
from openerp.tools.translate import _
|
||||
from openerp import exceptions
|
||||
from lxml import etree
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -434,6 +435,43 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
|
|||
def copy(self, cr, uid, id, values, context=None):
|
||||
raise osv.except_osv(_("Cannot duplicate configuration!"), "")
|
||||
|
||||
def fields_view_get(self, cr, user, view_id=None, view_type='form',
|
||||
context=None, toolbar=False, submenu=False):
|
||||
ret_val = super(res_config_settings, self).fields_view_get(
|
||||
cr, user, view_id=view_id, view_type=view_type, context=context,
|
||||
toolbar=toolbar, submenu=submenu)
|
||||
|
||||
doc = etree.XML(ret_val['arch'])
|
||||
|
||||
for field in ret_val['fields']:
|
||||
if not field.startswith("module_"):
|
||||
continue
|
||||
for node in doc.xpath("//field[@name='%s']" % field):
|
||||
if 'on_change' not in node.attrib:
|
||||
node.set("on_change",
|
||||
"onchange_module(%s, '%s')" % (field, field))
|
||||
|
||||
ret_val['arch'] = etree.tostring(doc)
|
||||
return ret_val
|
||||
|
||||
def onchange_module(self, cr, uid, ids, field_value, module_name, context={}):
|
||||
module_pool = self.pool.get('ir.module.module')
|
||||
module_ids = module_pool.search(
|
||||
cr, uid, [('name', '=', module_name.replace("module_", '')),
|
||||
('state','in', ['to install', 'installed', 'to upgrade'])],
|
||||
context=context)
|
||||
|
||||
if module_ids and not field_value:
|
||||
dep_ids = module_pool.downstream_dependencies(cr, uid, module_ids, context=context)
|
||||
dep_name = [x.shortdesc for x in module_pool.browse(
|
||||
cr, uid, dep_ids + module_ids, context=context)]
|
||||
message = '\n'.join(dep_name)
|
||||
return {'warning': {'title': _('Warning!'),
|
||||
'message':
|
||||
_('Disabling this option will also uninstall the following modules \n%s' % message)
|
||||
}}
|
||||
return {}
|
||||
|
||||
def _get_classified_fields(self, cr, uid, context=None):
|
||||
""" return a dictionary with the fields classified by category::
|
||||
|
||||
|
|
|
@ -268,8 +268,6 @@ class WebRequest(object):
|
|||
to abitrary responses. Anything returned (except None) will
|
||||
be used as response."""
|
||||
self._failed = exception # prevent tx commit
|
||||
if isinstance(exception, werkzeug.exceptions.HTTPException):
|
||||
return exception
|
||||
raise
|
||||
|
||||
def _call_function(self, *args, **kwargs):
|
||||
|
@ -531,6 +529,15 @@ class HttpRequest(WebRequest):
|
|||
params.pop('session_id', None)
|
||||
self.params = params
|
||||
|
||||
def _handle_exception(self, exception):
|
||||
"""Called within an except block to allow converting exceptions
|
||||
to abitrary responses. Anything returned (except None) will
|
||||
be used as response."""
|
||||
try:
|
||||
return super(HttpRequest, self)._handle_exception(exception)
|
||||
except werkzeug.exceptions.HTTPException, e:
|
||||
return e
|
||||
|
||||
def dispatch(self):
|
||||
if request.httprequest.method == 'OPTIONS' and request.endpoint and request.endpoint.routing.get('cors'):
|
||||
headers = {
|
||||
|
|
|
@ -46,8 +46,15 @@ SLEEP_INTERVAL = 60 # 1 min
|
|||
#----------------------------------------------------------
|
||||
# Werkzeug WSGI servers patched
|
||||
#----------------------------------------------------------
|
||||
class LoggingBaseWSGIServerMixIn(object):
|
||||
def handle_error(self, request, client_address):
|
||||
t, e, _ = sys.exc_info()
|
||||
if t == socket.error and e.errno == errno.EPIPE:
|
||||
# broken pipe, ignore error
|
||||
return
|
||||
_logger.exception('Exception happened during processing of request from %s', client_address)
|
||||
|
||||
class BaseWSGIServerNoBind(werkzeug.serving.BaseWSGIServer):
|
||||
class BaseWSGIServerNoBind(LoggingBaseWSGIServerMixIn, werkzeug.serving.BaseWSGIServer):
|
||||
""" werkzeug Base WSGI Server patched to skip socket binding. PreforkServer
|
||||
use this class, sets the socket and calls the process_request() manually
|
||||
"""
|
||||
|
@ -74,7 +81,7 @@ class RequestHandler(werkzeug.serving.WSGIRequestHandler):
|
|||
# should also work with systemd socket activation. This is currently untested
|
||||
# and not yet used.
|
||||
|
||||
class ThreadedWSGIServerReloadable(werkzeug.serving.ThreadedWSGIServer):
|
||||
class ThreadedWSGIServerReloadable(LoggingBaseWSGIServerMixIn, werkzeug.serving.ThreadedWSGIServer):
|
||||
""" werkzeug Threaded WSGI Server patched to allow reusing a listen socket
|
||||
given by the environement, this is used by autoreload to keep the listen
|
||||
socket open when a reload happens.
|
||||
|
|
Loading…
Reference in New Issue