[MERGE] forward port branch saas-15 up to 970be94f37

This commit is contained in:
Christophe Simonis
2017-12-05 16:46:14 +01:00
10 changed files with 109 additions and 62 deletions
+1 -1
View File
@@ -16,7 +16,7 @@
<field name="auth_endpoint">https://www.facebook.com/dialog/oauth</field>
<field name="scope">public_profile,email</field>
<field name="validation_endpoint">https://graph.facebook.com/me</field>
<field name="data_endpoint"></field>
<field name="data_endpoint">https://graph.facebook.com/me?fields=id,name,email</field>
<field name="css_class">fa fa-facebook-square</field>
<field name="body">Log in with facebook</field>
</record>
+1 -1
View File
@@ -81,7 +81,7 @@ class Serialized(fields.Field):
}
column_type = ('text', 'text')
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
return json.dumps(value)
def convert_to_cache(self, value, record, validate=True):
+1 -1
View File
@@ -301,7 +301,7 @@ var PosDB = core.Class.extend({
search_partner: function(query){
try {
query = query.replace(/[\[\]\(\)\+\*\?\.\-\!\&\^\$\|\~\_\{\}\:\,\\\/]/g,'.');
query = query.replace(' ','.+');
query = query.replace(/ /g,'.+');
var re = RegExp("([0-9]+):.*?"+query,"gi");
}catch(e){
return [];
+1 -1
View File
@@ -24,7 +24,7 @@ class CrmTeam(models.Model):
def _get_default_team_id(self, user_id=None):
if not user_id:
user_id = self.env.uid
company_id = self.sudo(user_id).company_id.id
company_id = self.sudo(user_id).env.user.company_id.id
team_id = self.env['crm.team'].sudo().search([
'|', ('user_id', '=', user_id), ('member_ids', '=', user_id),
'|', ('company_id', '=', False), ('company_id', 'child_of', [company_id])
@@ -339,7 +339,7 @@ var SearchView = Widget.extend({
},
set_default_filters: function () {
var self = this,
default_custom_filter = this.$buttons && this.favorite_menu.get_default_filter();
default_custom_filter = this.$buttons && this.favorite_menu && this.favorite_menu.get_default_filter();
if (!self.options.disable_custom_filters && default_custom_filter) {
return this.favorite_menu.toggle_filter(default_custom_filter, true);
}
+11
View File
@@ -0,0 +1,11 @@
China, 2017-12-05
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,
Ruter ruter.lv@gmail.com https://github.com/ruter
@@ -5,7 +5,7 @@ from datetime import date, datetime
from odoo.exceptions import AccessError, except_orm
from odoo.tests import common
from odoo.tools import mute_logger
from odoo.tools import mute_logger, float_repr
class TestFields(common.TransactionCase):
@@ -305,21 +305,65 @@ class TestFields(common.TransactionCase):
record.number = 2.4999999999999996
self.assertEqual(record.number, 2.50)
def check_monetary(self, record, amount, currency, msg=None):
# determine the possible roundings of amount
if currency:
ramount = currency.round(amount)
samount = float(float_repr(ramount, currency.decimal_places))
else:
ramount = samount = amount
# check the currency on record
self.assertEqual(record.currency_id, currency)
# check the value on the record
self.assertIn(record.amount, [ramount, samount], msg)
# check the value in the database
self.cr.execute('SELECT amount FROM test_new_api_mixed WHERE id=%s', [record.id])
value = self.cr.fetchone()[0]
self.assertEqual(value, samount, msg)
def test_20_monetary(self):
""" test monetary fields """
record = self.env['test_new_api.mixed'].create({})
self.assertTrue(record.currency_id)
self.assertEqual(record.currency_id.rounding, 0.01)
model = self.env['test_new_api.mixed']
currency = self.env['res.currency'].with_context(active_test=False)
amount = 14.70126
# the conversion to cache should round the value to 14.700000000000001
record.amount = 14.7
self.assertNotEqual(record.amount, 14.7)
self.assertEqual(record.amount, 14.700000000000001)
for rounding in [0.01, 0.0001, 1.0, 0]:
# first retrieve a currency corresponding to rounding
if rounding:
currency = currency.search([('rounding', '=', rounding)], limit=1)
self.assertTrue(currency, "No currency found for rounding %s" % rounding)
else:
# rounding=0 corresponds to currency=False
currency = currency.browse()
# however when stored to database, it should be serialized as 14.70
self.cr.execute('SELECT amount FROM test_new_api_mixed WHERE id=%s', (record.id,))
(amount,) = self.cr.fetchone()
self.assertEqual(amount, 14.7)
# case 1: create with amount and currency
record = model.create({'amount': amount, 'currency_id': currency.id})
self.check_monetary(record, amount, currency, 'create(amount, currency)')
# case 2: assign amount
record.amount = 0
record.amount = amount
self.check_monetary(record, amount, currency, 'assign(amount)')
# case 3: write with amount and currency
record.write({'amount': 0, 'currency_id': False})
record.write({'amount': amount, 'currency_id': currency.id})
self.check_monetary(record, amount, currency, 'write(amount, currency)')
# case 4: write with amount only
record.write({'amount': 0})
record.write({'amount': amount})
self.check_monetary(record, amount, currency, 'write(amount)')
# case 5: write with amount on several records
records = record + model.create({'currency_id': currency.id})
records.write({'amount': 0})
records.write({'amount': amount})
for record in records:
self.check_monetary(record, amount, currency, 'multi write(amount)')
def test_21_date(self):
""" test date fields """
+31 -23
View File
@@ -19,7 +19,7 @@ except ImportError:
import psycopg2
from odoo.sql_db import LazyCursor
from odoo.tools import float_precision, float_repr, float_round, frozendict, html_sanitize, human_size, pg_varchar, ustr, OrderedSet, pycompat
from odoo.tools import float_repr, float_round, frozendict, html_sanitize, human_size, pg_varchar, ustr, OrderedSet, pycompat
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT as DATETIME_FORMAT
from odoo.tools.translate import html_translate, _
@@ -776,7 +776,7 @@ class Field(object):
""" Return the null value for this field in the record format. """
return False
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
""" Convert ``value`` from the ``write`` format to the SQL format. """
if value is None or value is False:
return None
@@ -1180,7 +1180,7 @@ class Boolean(Field):
type = 'boolean'
column_type = ('bool', 'bool')
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
return bool(value)
def convert_to_cache(self, value, record, validate=True):
@@ -1201,7 +1201,7 @@ class Integer(Field):
_description_group_operator = property(attrgetter('group_operator'))
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
return int(value or 0)
def convert_to_cache(self, value, record, validate=True):
@@ -1265,7 +1265,7 @@ class Float(Field):
_description_digits = property(attrgetter('digits'))
_description_group_operator = property(attrgetter('group_operator'))
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
result = float(value or 0.0)
digits = self.digits
if digits:
@@ -1319,25 +1319,33 @@ class Monetary(Field):
assert self.currency_field in model._fields, \
"Field %s with unknown currency_field %r" % (self, self.currency_field)
def convert_to_column(self, value, record):
try:
return value.float_repr() # see float_precision.float_repr()
except Exception:
return float(value or 0.0)
def convert_to_column(self, value, record, values=None):
# retrieve currency from values or record
if values and self.currency_field in values:
field = record._fields[self.currency_field]
currency = field.convert_to_cache(values[self.currency_field], record)
currency = field.convert_to_record(currency, record)
else:
# Note: this is wrong if 'record' is several records with different
# currencies, which is functional nonsense and should not happen
currency = record[:1][self.currency_field]
value = float(value or 0.0)
if currency:
return float_repr(currency.round(value), currency.decimal_places)
return value
def convert_to_cache(self, value, record, validate=True):
if validate:
currency = record[self.currency_field]
# cache format: float
value = float(value or 0.0)
if validate and record[self.currency_field]:
# FIXME @rco-odoo: currency may not be already initialized if it is
# a function or related field!
if currency:
value = currency.round(float(value or 0.0))
return float_precision(value, currency.decimal_places)
return float(value or 0.0)
value = record[self.currency_field].round(value)
return value
def convert_to_read(self, value, record, use_name_get=True):
# float_precision values are not supported in pure XMLRPC
return float(value)
return value
def convert_to_write(self, value, record):
return value
@@ -1438,7 +1446,7 @@ class Char(_String):
assert isinstance(self.size, (NoneType, int)), \
"Char field %s with non-integer size %r" % (self, self.size)
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
if value is None or value is False:
return None
# we need to convert the string to a unicode object to be able
@@ -1503,7 +1511,7 @@ class Html(_String):
_description_strip_style = property(attrgetter('strip_style'))
_description_strip_classes = property(attrgetter('strip_classes'))
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
if value is None or value is False:
return None
if self.sanitize:
@@ -1684,7 +1692,7 @@ class Binary(Field):
_description_attachment = property(attrgetter('attachment'))
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
# Binary values may be byte strings (python 2.6 byte array), but
# the legacy OpenERP convention is to transfer and store binaries
# as base64-encoded strings. The base64 string may be provided as a
@@ -1844,7 +1852,7 @@ class Selection(Field):
return item[1]
return False
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
""" Convert ``value`` from the ``write`` format to the SQL format. """
if value is None or value is False:
return None
@@ -2011,7 +2019,7 @@ class Many2one(_Relational):
"""
records._cache[self] = self.convert_to_cache(value, records, validate=False)
def convert_to_column(self, value, record):
def convert_to_column(self, value, record, values=None):
return value or None
def convert_to_cache(self, value, record, validate=True):
+6 -4
View File
@@ -3083,7 +3083,7 @@ class BaseModel(object):
if field.column_type:
if single_lang or not (has_trans and field.translate is True):
# val is not a translation: update the table
val = field.convert_to_column(val, self)
val = field.convert_to_column(val, self, vals)
updates.append((name, field.column_format, val))
direct.append(name)
else:
@@ -3123,7 +3123,7 @@ class BaseModel(object):
# Insert value to DB
src_trans = vals[name]
self.with_context(lang=None).write({name: src_trans})
val = field.convert_to_column(vals[name], self)
val = field.convert_to_column(vals[name], self, vals)
tname = "%s,%s" % (self._name, name)
self.env['ir.translation']._set_ids(
tname, 'model', self.env.lang, self.ids, val, src_trans)
@@ -3347,7 +3347,7 @@ class BaseModel(object):
parent_id = self.env[parent_model].create(parent_vals).id
else:
self.env[parent_model].browse(parent_id).write(parent_vals)
updates.append((self._inherits[parent_model], '%s', parent_id))
vals[self._inherits[parent_model]] = parent_id
# set boolean fields to False by default (to make search more powerful)
for name, field in self._fields.iteritems():
@@ -3355,10 +3355,12 @@ class BaseModel(object):
vals[name] = False
# determine SQL values
self = self.browse()
for name, val in vals.iteritems():
field = self._fields[name]
if field.store and field.column_type:
updates.append((name, field.column_format, field.convert_to_column(val, self)))
column_val = field.convert_to_column(val, self, vals)
updates.append((name, field.column_format, column_val))
else:
upd_todo.append(name)
-18
View File
@@ -180,24 +180,6 @@ def float_split(value, precision_digits):
return int(units), int(cents)
class float_precision(float):
""" A class for float values that carry precision digits. This is a thin
layer on top of ``float``, and the precision digits are not propagated
to the result of arithmetic operations. This class is used when
converting monetary values to cache, and for serializing them to the
database.
"""
__slots__ = ['precision_digits']
def __new__(cls, value, precision_digits):
obj = super(float_precision, cls).__new__(cls, value)
obj.precision_digits = precision_digits
return obj
def float_repr(self):
return _float_repr(self, self.precision_digits)
if __name__ == "__main__":
import time