[MERGE] forward port branch 10.0 up to de62e33618

This commit is contained in:
Christophe Simonis
2018-02-19 17:07:29 +01:00
10 changed files with 116 additions and 52 deletions
+2 -1
View File
@@ -76,7 +76,8 @@ bus.Bus = Widget.extend({
this.last_partners_presence_check = now;
}
var data = {channels: self.channels, last: self.last, options: options};
session.rpc('/longpolling/poll', data, {shadow : true}).then(function(result) {
// The backend has a maximum cycle time of 50 seconds so give +10 seconds
session.rpc('/longpolling/poll', data, {shadow : true, timeout: 60000}).then(function(result) {
self.on_notification(result);
if(!self.stop){
self.poll();
+1 -1
View File
@@ -405,7 +405,7 @@ class AlarmManager(models.AbstractModel):
result = False
if alarm.type == 'email':
result = meeting.attendee_ids._send_mail_to_attendees('calendar.calendar_template_meeting_reminder', force_send=True)
result = meeting.attendee_ids.filtered(lambda r: r.state != 'declined')._send_mail_to_attendees('calendar.calendar_template_meeting_reminder', force_send=True)
return result
def do_notif_reminder(self, alert):
+1 -1
View File
@@ -268,7 +268,7 @@ class EventEvent(models.Model):
return res
@api.one
def mail_attendees(self, template_id, force_send=False, filter_func=lambda self: True):
def mail_attendees(self, template_id, force_send=False, filter_func=lambda self: self.state != 'cancel'):
for attendee in self.registration_ids.filtered(filter_func):
self.env['mail.template'].browse(template_id).send_mail(attendee.id, force_send=force_send)
+1 -1
View File
@@ -1336,7 +1336,7 @@ class ExportFormat(object):
model, fields, ids, domain, import_compat = \
operator.itemgetter('model', 'fields', 'ids', 'domain', 'import_compat')(params)
Model = request.env[model].with_context(**params.get('context', {}))
Model = request.env[model].with_context(import_compat=import_compat, **params.get('context', {}))
records = Model.browse(ids) or Model.search(domain, offset=0, limit=False, order=False)
if not Model._is_an_ordinary_table():
+7 -4
View File
@@ -98,12 +98,15 @@
</t>
<t t-set="x_icon" t-value="'/web/image/website/%s/favicon/' % website.id"/>
<t t-set="head_website">
<meta name="description" t-att-content="main_object and 'website_meta_description' in main_object
and main_object.website_meta_description or website_meta_description"/>
<meta name="keywords" t-att-content="main_object and 'website_meta_keywords' in main_object
and main_object.website_meta_keywords or website_meta_keywords"/>
<meta name="generator" content="Odoo"/>
<t t-set="meta_description" t-value="main_object and 'website_meta_description' in main_object
and main_object.website_meta_description or website_meta_description"/>
<t t-set="meta_keywords" t-value="main_object and 'website_meta_keywords' in main_object
and main_object.website_meta_keywords or website_meta_keywords"/>
<meta t-if="meta_description" name="description" t-att-content="meta_description"/>
<meta t-if="meta_keywords" name="keywords" t-att-content="meta_keywords"/>
<!-- OpenGraph tags for Facebook sharing -->
<meta property="og:title" t-att-content="additional_title" />
<meta property="og:site_name" t-att-content="res_company.name" />
+10
View File
@@ -0,0 +1,10 @@
Norway, 2018-02-08
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Marius Stedjan marius@stedjan.com https://github.com/willmakenoise
+2 -2
View File
@@ -54,7 +54,7 @@ Running the server
Maximum allowed virtual memory per worker. If the limit is exceeded,
the worker is killed and recycled at the end of the current request.
Defaults to 640MB.
Defaults to 2048MB.
.. option:: --limit-memory-hard <limit>
@@ -62,7 +62,7 @@ Running the server
immediately killed without waiting for the end of the current request
processing.
Defaults to 768MB.
Defaults to 2560MB.
.. option:: --limit-time-cpu <limit>
+48 -1
View File
@@ -600,7 +600,54 @@ class test_m2m(CreatorCase):
['', u'export.many2many.other:13'],
])
# essentially same as o2m, so boring
def test_multiple_records_subfield(self):
r = self.make(self.commands)
xid = self.env['ir.model.data'].create({
'name': 'whopwhopwhop',
'module': '__t__',
'model': r._name,
'res_id': r.id,
}).complete_name
sids = [
self.env['ir.model.data'].create({
'name': sub.str,
'module': '__t__',
'model': sub._name,
'res_id': sub.id,
}).complete_name
for sub in r.value
]
r.invalidate_cache()
self.assertEqual(
r._export_rows([['value', 'id']]),
[['__t__.record000,__t__.record001,__t__.record010,__t__.record011,__t__.record100']]
)
self.assertEqual(
r.with_context(import_compat=True)._export_rows([['value', 'id']]),
[['__t__.record000,__t__.record001,__t__.record010,__t__.record011,__t__.record100']]
)
self.assertEqual(
r.with_context(import_compat=False)._export_rows([['id'], ['value', 'id'], ['value', 'value']]),
[
[xid, u'__t__.record000', u'4'],
[u'', u'__t__.record001', u'42'],
[u'', u'__t__.record010', u'36'],
[u'', u'__t__.record011', u'4'],
[u'', u'__t__.record100', u'13']
]
)
self.assertEqual(
r.with_context(import_compat=False)._export_rows([['id'], ['value', 'value'], ['value', 'id']]),
[
[xid, u'4', u'__t__.record000'],
[u'', u'42', u'__t__.record001'],
[u'', u'36', u'__t__.record010'],
[u'', u'4', u'__t__.record011'],
[u'', u'13', u'__t__.record100']
]
)
class test_function(CreatorCase):
+43 -40
View File
@@ -758,6 +758,7 @@ class BaseModel(object):
:param fields: list of lists of fields to traverse
:return: list of lists of corresponding values
"""
import_compatible = self.env.context.get('import_compat', True)
lines = []
for record in self:
# main line of record, initially empty
@@ -791,8 +792,9 @@ class BaseModel(object):
else:
primary_done.append(name)
# This is a special case, its strange behavior is intended!
if field.type == 'many2many' and len(path) > 1 and path[1] == 'id':
# in import_compat mode, m2m should always be exported as
# a comma-separated list of xids in a single cell
if import_compatible and field.type == 'many2many' and len(path) > 1 and path[1] == 'id':
xml_ids = [r.__export_xml_id() for r in value]
current[i] = ','.join(xml_ids) or False
continue
@@ -3353,51 +3355,52 @@ class BaseModel(object):
raise UserError(_('Unable to delete this document because it is used as a default property'))
# Delete the records' properties.
self.env['ir.property'].search([('res_id', 'in', refs)]).unlink()
with self.env.norecompute():
self.env['ir.property'].search([('res_id', 'in', refs)]).unlink()
self.check_access_rule('unlink')
self.check_access_rule('unlink')
cr = self._cr
Data = self.env['ir.model.data'].sudo().with_context({})
Values = self.env['ir.values']
Attachment = self.env['ir.attachment']
cr = self._cr
Data = self.env['ir.model.data'].sudo().with_context({})
Values = self.env['ir.values']
Attachment = self.env['ir.attachment']
for sub_ids in cr.split_for_in_conditions(self.ids):
query = "DELETE FROM %s WHERE id IN %%s" % self._table
cr.execute(query, (sub_ids,))
for sub_ids in cr.split_for_in_conditions(self.ids):
query = "DELETE FROM %s WHERE id IN %%s" % self._table
cr.execute(query, (sub_ids,))
# Removing the ir_model_data reference if the record being deleted
# is a record created by xml/csv file, as these are not connected
# with real database foreign keys, and would be dangling references.
#
# Note: the following steps are performed as superuser to avoid
# access rights restrictions, and with no context to avoid possible
# side-effects during admin calls.
data = Data.search([('model', '=', self._name), ('res_id', 'in', sub_ids)])
if data:
data.unlink()
# Removing the ir_model_data reference if the record being deleted
# is a record created by xml/csv file, as these are not connected
# with real database foreign keys, and would be dangling references.
#
# Note: the following steps are performed as superuser to avoid
# access rights restrictions, and with no context to avoid possible
# side-effects during admin calls.
data = Data.search([('model', '=', self._name), ('res_id', 'in', sub_ids)])
if data:
data.unlink()
# For the same reason, remove the relevant records in ir_values
refs = ['%s,%s' % (self._name, i) for i in sub_ids]
values = Values.search(['|', ('value', 'in', refs),
'&', ('model', '=', self._name),
('res_id', 'in', sub_ids)])
if values:
values.unlink()
# For the same reason, remove the relevant records in ir_values
refs = ['%s,%s' % (self._name, i) for i in sub_ids]
values = Values.search(['|', ('value', 'in', refs),
'&', ('model', '=', self._name),
('res_id', 'in', sub_ids)])
if values:
values.unlink()
# For the same reason, remove the relevant records in ir_attachment
# (the search is performed with sql as the search method of
# ir_attachment is overridden to hide attachments of deleted
# records)
query = 'SELECT id FROM ir_attachment WHERE res_model=%s AND res_id IN %s'
cr.execute(query, (self._name, sub_ids))
attachments = Attachment.browse([row[0] for row in cr.fetchall()])
if attachments:
attachments.unlink()
# For the same reason, remove the relevant records in ir_attachment
# (the search is performed with sql as the search method of
# ir_attachment is overridden to hide attachments of deleted
# records)
query = 'SELECT id FROM ir_attachment WHERE res_model=%s AND res_id IN %s'
cr.execute(query, (self._name, sub_ids))
attachments = Attachment.browse([row[0] for row in cr.fetchall()])
if attachments:
attachments.unlink()
# invalidate the *whole* cache, since the orm does not handle all
# changes made in the database, like cascading delete!
self.invalidate_cache()
# invalidate the *whole* cache, since the orm does not handle all
# changes made in the database, like cascading delete!
self.invalidate_cache()
# recompute new-style fields
if self.env.recompute and self._context.get('recompute', True):
+1 -1
View File
@@ -65,7 +65,7 @@ def xmlrpc_return(start_response, service, method, params, string_faultcode=Fals
def xmlrpc_handle_exception_int(e):
if isinstance(e, odoo.exceptions.UserError):
fault = xmlrpclib.Fault(RPC_FAULT_CODE_WARNING, odoo.tools.ustr(e.value))
fault = xmlrpclib.Fault(RPC_FAULT_CODE_WARNING, odoo.tools.ustr(e.name))
response = xmlrpclib.dumps(fault, allow_none=False, encoding=None)
elif isinstance(e, odoo.exceptions.RedirectWarning):
fault = xmlrpclib.Fault(RPC_FAULT_CODE_WARNING, str(e))