[MERGE] forward port of branch saas-6 up to b87a93a
This commit is contained in:
@@ -709,6 +709,9 @@ class AccountInvoice(models.Model):
|
||||
line2[tmp]['credit'] = (am < 0) and -am or 0.0
|
||||
line2[tmp]['amount_currency'] += l['amount_currency']
|
||||
line2[tmp]['analytic_line_ids'] += l['analytic_line_ids']
|
||||
qty = l.get('quantity')
|
||||
if qty:
|
||||
line2[tmp]['quantity'] = line2[tmp].get('quantity', 0.0) + qty
|
||||
else:
|
||||
line2[tmp] = l
|
||||
line = []
|
||||
|
||||
@@ -711,8 +711,9 @@ class product_template(osv.osv):
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
template = self.browse(cr, uid, id, context=context)
|
||||
default['name'] = _("%s (copy)") % (template['name'])
|
||||
if 'name' not in default:
|
||||
template = self.browse(cr, uid, id, context=context)
|
||||
default['name'] = _("%s (copy)") % (template['name'])
|
||||
return super(product_template, self).copy(cr, uid, id, default=default, context=context)
|
||||
|
||||
_defaults = {
|
||||
|
||||
@@ -241,7 +241,7 @@ with directly by external objects or search view controls
|
||||
.. js:class:: openerp.web.search.Facet
|
||||
|
||||
A `backbone model`_ representing a single facet of the current
|
||||
research. May map to a search field, or to a more complex or
|
||||
search. May map to a search field, or to a more complex or
|
||||
fuzzier input (e.g. a custom filter or an advanced search).
|
||||
|
||||
.. js:attribute:: category
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Austria, 2016-06-16
|
||||
|
||||
Seekda GmbH agrees to the terms of the Odoo Corporate Contributor License
|
||||
Agreement v1.0.
|
||||
|
||||
I declare that I am authorized and able to make this agreement and sign this
|
||||
declaration.
|
||||
|
||||
Signed,
|
||||
|
||||
Holger Lausen holger.lausen@seekda.com https://github.com/holgerlausen
|
||||
|
||||
List of contributors:
|
||||
|
||||
Holger Lausen holger.lausen@seekda.com https://github.com/holgerlausen
|
||||
Florian Kisser florian.kisser@seekda.com https://github.com/floriankisser
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Nicaragua, Jun 16th, 2016
|
||||
|
||||
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,
|
||||
|
||||
William Moreno williamjmorenor@gmail.com https://github.com/williamjmorenor
|
||||
@@ -641,7 +641,7 @@ Model Reference
|
||||
.. automethod:: read
|
||||
.. automethod:: read_group
|
||||
|
||||
.. rubric:: Research
|
||||
.. rubric:: Searching
|
||||
|
||||
.. automethod:: search
|
||||
.. automethod:: search_count
|
||||
|
||||
@@ -815,7 +815,7 @@ attributes:
|
||||
|
||||
``default_group_by``
|
||||
whether the kanban view should be grouped if no grouping is specified via
|
||||
the action or the current research. Should be the name of the field to group
|
||||
the action or the current search. Should be the name of the field to group
|
||||
by when no grouping is otherwise specified
|
||||
``default_order``
|
||||
cards sorting order used if the user has not already sorted the records (via
|
||||
|
||||
@@ -4,6 +4,7 @@ access_test_new_api_bravo,access_test_new_api_bravo,model_test_new_api_bravo,,1,
|
||||
access_category,test_new_api_category,test_new_api.model_test_new_api_category,,1,1,1,1
|
||||
access_discussion,test_new_api_discussion,test_new_api.model_test_new_api_discussion,,1,1,1,1
|
||||
access_message,test_new_api_message,test_new_api.model_test_new_api_message,,1,1,1,1
|
||||
access_emailmessage,test_new_api_emailmessage,test_new_api.model_test_new_api_emailmessage,,1,1,1,1
|
||||
access_multi,test_new_api_multi,test_new_api.model_test_new_api_multi,,1,1,1,1
|
||||
access_multi_line,test_new_api_multi_line,test_new_api.model_test_new_api_multi_line,,1,1,1,1
|
||||
access_mixed,test_new_api_mixed,test_new_api.model_test_new_api_mixed,,1,1,1,1
|
||||
|
||||
|
@@ -130,6 +130,9 @@ class Discussion(models.Model):
|
||||
message_concat = fields.Text(string='Message concatenate')
|
||||
important_messages = fields.One2many('test_new_api.message', 'discussion',
|
||||
domain=[('important', '=', True)])
|
||||
emails = fields.One2many('test_new_api.emailmessage', 'discussion')
|
||||
important_emails = fields.One2many('test_new_api.emailmessage', 'discussion',
|
||||
domain=[('important', '=', True)])
|
||||
|
||||
@api.onchange('moderator')
|
||||
def _onchange_moderator(self):
|
||||
@@ -210,6 +213,14 @@ class Message(models.Model):
|
||||
return [('author.partner_id', operator, value)]
|
||||
|
||||
|
||||
class EmailMessage(models.Model):
|
||||
_name = 'test_new_api.emailmessage'
|
||||
_inherits = {'test_new_api.message': 'message'}
|
||||
|
||||
message = fields.Many2one('test_new_api.message', 'Message',
|
||||
required=True, ondelete='cascade')
|
||||
email_to = fields.Char('To')
|
||||
|
||||
class Multi(models.Model):
|
||||
""" Model for testing multiple onchange methods in cascade that modify a
|
||||
one2many field several times.
|
||||
|
||||
@@ -12,6 +12,7 @@ class TestOnChange(common.TransactionCase):
|
||||
super(TestOnChange, self).setUp()
|
||||
self.Discussion = self.env['test_new_api.discussion']
|
||||
self.Message = self.env['test_new_api.message']
|
||||
self.EmailMessage = self.env['test_new_api.emailmessage']
|
||||
|
||||
def test_default_get(self):
|
||||
""" checking values returned by default_get() """
|
||||
@@ -223,3 +224,60 @@ class TestOnChange(common.TransactionCase):
|
||||
self.assertIn('message_concat', result['value'])
|
||||
self.assertEqual(result['value']['message_concat'],
|
||||
"\n".join(["%s:%s" % (m.name, m.body) for m in discussion.messages]))
|
||||
|
||||
def test_onchange_one2many_with_domain_on_related_field(self):
|
||||
""" test the value of the one2many field when defined with a domain on a related field"""
|
||||
discussion = self.env.ref('test_new_api.discussion_0')
|
||||
demo = self.env.ref('base.user_demo')
|
||||
|
||||
# mimic UI behaviour, so we get subfields
|
||||
# (we need at least subfield: 'important_emails.important')
|
||||
view_info = self.Discussion.fields_view_get(
|
||||
view_id=self.env.ref('test_new_api.discussion_form').id,
|
||||
view_type='form')
|
||||
field_onchange = self.Discussion._onchange_spec(view_info=view_info)
|
||||
self.assertEqual(field_onchange.get('messages'), '1')
|
||||
|
||||
BODY = "What a beautiful day!"
|
||||
USER = self.env.user
|
||||
|
||||
# create standalone email
|
||||
email = self.EmailMessage.create({
|
||||
'discussion': discussion.id,
|
||||
'name': "[%s] %s" % ('', USER.name),
|
||||
'body': BODY,
|
||||
'author': USER.id,
|
||||
'important': False,
|
||||
})
|
||||
|
||||
# check if server-side cache is working correctly
|
||||
self.env.invalidate_all()
|
||||
self.assertIn(email, discussion.emails)
|
||||
self.assertNotIn(email, discussion.important_emails)
|
||||
email.important = True
|
||||
self.assertIn(email, discussion.important_emails)
|
||||
|
||||
# check that when trigger an onchange, we don't reset important emails
|
||||
# (force `invalidate_all` as but appear in onchange only when we get a
|
||||
# cache miss)
|
||||
self.env.invalidate_all()
|
||||
self.assertEqual(len(discussion.messages), 4)
|
||||
values = {
|
||||
'name': "Foo Bar",
|
||||
'moderator': demo.id,
|
||||
'categories': [(4, cat.id) for cat in discussion.categories],
|
||||
'messages': [(4, msg.id) for msg in discussion.messages],
|
||||
'participants': [(4, usr.id) for usr in discussion.participants],
|
||||
'message_changes': 0,
|
||||
'important_messages': [(4, msg.id) for msg in discussion.important_messages],
|
||||
'important_emails': [(4, eml.id) for eml in discussion.important_emails],
|
||||
}
|
||||
result = discussion.onchange(values, 'name', field_onchange)
|
||||
|
||||
# When one2many domain contains non-computed field, things are ok
|
||||
self.assertEqual(result['value']['important_messages'],
|
||||
[(1, email.message.id, {'name': u'[Foo Bar] %s' % USER.name})])
|
||||
|
||||
# But here with commit 5676d81, we get value of: [(2, email.id)]
|
||||
self.assertEqual(result['value']['important_emails'],
|
||||
[(1, email.id, {'name': u'[Foo Bar] %s' % USER.name})])
|
||||
|
||||
@@ -59,12 +59,35 @@
|
||||
<tree string="Messages">
|
||||
<field name="name"/>
|
||||
<field name="body"/>
|
||||
<field name="important"/>
|
||||
</tree>
|
||||
<form string="Message" version="7.0">
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="author"/>
|
||||
<field name="size"/>
|
||||
<field name="important"/>
|
||||
</group>
|
||||
<label for="body"/>
|
||||
<field name="body"/>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Emails">
|
||||
<field name="important_emails">
|
||||
<tree name="Important Messages">
|
||||
<field name="name"/>
|
||||
<field name="body"/>
|
||||
<field name="important"/>
|
||||
<field name="email_to"/>
|
||||
</tree>
|
||||
<form string="Important Message" version="7.0">
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="author"/>
|
||||
<field name="size"/>
|
||||
<field name="important"/>
|
||||
<field name="email_to"/>
|
||||
</group>
|
||||
<label for="body"/>
|
||||
<field name="body"/>
|
||||
|
||||
@@ -1014,6 +1014,13 @@ class Field(object):
|
||||
# ``records``, except fields currently being computed
|
||||
spec = []
|
||||
for field, path in records._field_triggers[self]:
|
||||
if not field.compute:
|
||||
# Note: do not invalidate non-computed fields. Such fields may
|
||||
# require invalidation in general (like *2many fields with
|
||||
# domains) but should not be invalidated in this case, because
|
||||
# we would simply lose their values during an onchange!
|
||||
continue
|
||||
|
||||
target = env[field.model_name]
|
||||
computed = target.browse(env.computed[field])
|
||||
if path == 'id' and field.model_name == records._name:
|
||||
|
||||
+1
-1
@@ -2583,8 +2583,8 @@ class BaseModel(object):
|
||||
self._set_default_value_on_column(cr, k, context=context)
|
||||
# add the NOT NULL constraint
|
||||
try:
|
||||
cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % (self._table, k), log_exceptions=False)
|
||||
cr.commit()
|
||||
cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % (self._table, k), log_exceptions=False)
|
||||
_schema.debug("Table '%s': column '%s': added NOT NULL constraint",
|
||||
self._table, k)
|
||||
except Exception:
|
||||
|
||||
Reference in New Issue
Block a user