Skip to content

Commit

Permalink
[MERGE] forward port branch saas-15 up to 970be94
Browse files Browse the repository at this point in the history
  • Loading branch information
KangOl committed Dec 5, 2017
2 parents 5195550 + 970be94 commit b8540ee
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 64 deletions.
2 changes: 1 addition & 1 deletion addons/auth_oauth/data/auth_oauth_data.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion addons/base_sparse_field/models/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion addons/point_of_sale/static/src/js/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 [];
Expand Down
2 changes: 1 addition & 1 deletion addons/sales_team/models/crm_team.py
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down
2 changes: 1 addition & 1 deletion addons/web/static/src/js/chrome/search_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
11 changes: 11 additions & 0 deletions doc/cla/individual/ruter.md
Original file line number Diff line number Diff line change
@@ -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 [email protected] https://github.com/ruter
72 changes: 58 additions & 14 deletions odoo/addons/test_new_api/tests/test_new_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

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):
Expand Down Expand Up @@ -305,21 +305,65 @@ def test_20_float(self):
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)

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

# 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)
model = self.env['test_new_api.mixed']
currency = self.env['res.currency'].with_context(active_test=False)
amount = 14.70126

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

# 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 """
Expand Down
54 changes: 31 additions & 23 deletions odoo/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
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, _
Expand Down Expand Up @@ -776,7 +776,7 @@ def null(self, record):
""" 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
Expand Down Expand Up @@ -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):
Expand All @@ -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):
Expand Down Expand Up @@ -1265,7 +1265,7 @@ def digits(self):
_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:
Expand Down Expand Up @@ -1319,25 +1319,33 @@ def _setup_regular_full(self, model):
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
Expand Down Expand Up @@ -1438,7 +1446,7 @@ def _setup_regular_base(self, model):
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
Expand Down Expand Up @@ -1503,7 +1511,7 @@ def _setup_attrs(self, model, name):
_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:
Expand Down Expand Up @@ -1684,7 +1692,7 @@ def column_type(self):

_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
Expand Down Expand Up @@ -1844,7 +1852,7 @@ def convert_to_export(self, value, record):
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
Expand Down Expand Up @@ -2011,7 +2019,7 @@ def _update(self, records, value):
"""
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):
Expand Down
10 changes: 6 additions & 4 deletions odoo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3083,7 +3083,7 @@ def _write(self, vals):
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:
Expand Down Expand Up @@ -3123,7 +3123,7 @@ def _write(self, vals):
# 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)
Expand Down Expand Up @@ -3347,18 +3347,20 @@ def _create(self, vals):
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():
if field.type == 'boolean' and field.store and name not in vals:
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)

Expand Down
18 changes: 0 additions & 18 deletions odoo/tools/float_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit b8540ee

Please sign in to comment.