Skip to content

Commit

Permalink
[MERGE] forward port branch saas-15 up to 482370d
Browse files Browse the repository at this point in the history
  • Loading branch information
KangOl committed Feb 20, 2018
2 parents 77fa922 + 482370d commit 98d01e4
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 57 deletions.
3 changes: 2 additions & 1 deletion addons/bus/static/src/js/bus.js
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion addons/calendar/models/calendar.py
Expand Up @@ -415,7 +415,7 @@ def do_mail_reminder(self, alert):

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):
Expand Down
2 changes: 1 addition & 1 deletion addons/event/models/event.py
Expand Up @@ -319,7 +319,7 @@ def button_confirm(self):
self.state = 'confirm'

@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)

Expand Down
2 changes: 1 addition & 1 deletion addons/sales_team/models/crm_team.py
Expand Up @@ -225,7 +225,7 @@ def get_week_name(start_date, locale):
values[index][y_field] = data_item.get('y_value')

elif self.dashboard_graph_group == 'week':
weeks_in_start_year = int(date(start_date.year, 12, 31).isocalendar()[1])
weeks_in_start_year = int(date(start_date.year, 12, 28).isocalendar()[1]) # This date is always in the last week of ISO years
for week in range(0, (end_date.isocalendar()[1] - start_date.isocalendar()[1]) % weeks_in_start_year + 1):
short_name = get_week_name(start_date + relativedelta(days=7 * week), locale)
values.append({x_field: short_name, y_field: 0})
Expand Down
2 changes: 1 addition & 1 deletion addons/web/controllers/main.py
Expand Up @@ -1352,7 +1352,7 @@ def base(self, data, token):
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():
Expand Down
9 changes: 6 additions & 3 deletions addons/website/views/website_templates.xml
Expand Up @@ -104,11 +104,14 @@
</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
<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"/>
<meta name="keywords" t-att-content="main_object and 'website_meta_keywords' in main_object
<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 name="generator" content="Odoo"/>
<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" />
Expand Down
4 changes: 2 additions & 2 deletions addons/website_event/models/event.py
Expand Up @@ -32,8 +32,8 @@ class Event(models.Model):
website_menu = fields.Boolean(
'Dedicated Menu', compute='_compute_website_menu', inverse='_set_website_menu',
help="Creates menus Introduction, Location and Register on the page "
" of the event on the website.", store=True, copy=False)
menu_id = fields.Many2one('website.menu', 'Event Menu')
" of the event on the website.", store=True)
menu_id = fields.Many2one('website.menu', 'Event Menu', copy=False)

def _compute_is_participating(self):
# we don't allow public user to see participating label
Expand Down
10 changes: 10 additions & 0 deletions doc/cla/individual/willmakenoise.md
@@ -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
4 changes: 2 additions & 2 deletions doc/reference/cmdline.rst
Expand Up @@ -54,15 +54,15 @@ 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>

Hard limit on virtual memory, any worker exceeding the limit will be
immediately killed without waiting for the end of the current request
processing.

Defaults to 768MB.
Defaults to 2560MB.

.. option:: --limit-time-cpu <limit>

Expand Down
49 changes: 48 additions & 1 deletion odoo/addons/test_impex/tests/test_export.py
Expand Up @@ -600,7 +600,54 @@ def test_multiple_records_name(self):
['', 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):
Expand Down
89 changes: 46 additions & 43 deletions odoo/models.py
Expand Up @@ -646,6 +646,7 @@ def _export_rows(self, fields):
: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
Expand Down Expand Up @@ -679,8 +680,9 @@ def _export_rows(self, fields):
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
Expand Down Expand Up @@ -2852,51 +2854,52 @@ def unlink(self):
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()

# 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()

# invalidate the *whole* cache, since the orm does not handle all
# changes made in the database, like cascading delete!
self.invalidate_cache()
# 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_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()

# recompute new-style fields
if self.env.recompute and self._context.get('recompute', True):
Expand Down
2 changes: 1 addition & 1 deletion odoo/service/wsgi_server.py
Expand Up @@ -63,7 +63,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))
Expand Down

0 comments on commit 98d01e4

Please sign in to comment.