From 5a5c2dbbf8da82d5882f929fbb2527f23bd99619 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Tue, 6 Dec 2022 14:47:56 +0000 Subject: [PATCH] [FIX] web: handle float fields with digits=0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the orm documentation, the `digits` attribute of float fields must be either a tuple (int, int) or a string. However, people set `digits=0` on a bunch of float fields (some are there for a while now). Historically, the webclient handled this as "there's no digits attribute set", so it fallbacked on 2 digits precision. With the new views, and owl props validation, we assert that the `digits` props, when given, is an array. In the above situations, we have a props validation error. This commit fixes the error by filtering out the `digits` props when it is not an array, s.t. it keeps working as before (i.e. fallbacks on 2 digits). In master, we'll remove the fallback. opw 3083100 closes odoo/odoo#107418 X-original-commit: 36407a9837ba3bf90670ae763751dc631309867b Signed-off-by: Michaƫl Mattiello --- .../src/views/fields/float/float_field.js | 14 ++++++++--- .../fields/float_toggle/float_toggle_field.js | 10 +++++++- .../fields/percentage/percentage_field.js | 10 +++++++- .../views/fields/stat_info/stat_info_field.js | 10 +++++++- .../tests/views/fields/float_field_tests.js | 23 +++++++++++++++++++ 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/addons/web/static/src/views/fields/float/float_field.js b/addons/web/static/src/views/fields/float/float_field.js index 6b5d50efbcb..ade8dd2daf0 100644 --- a/addons/web/static/src/views/fields/float/float_field.js +++ b/addons/web/static/src/views/fields/float/float_field.js @@ -49,12 +49,20 @@ FloatField.supportedTypes = ["float"]; FloatField.isEmpty = () => false; FloatField.extractProps = ({ attrs, field }) => { + // Sadly, digits param was available as an option and an attr. + // The option version could be removed with some xml refactoring. + let digits; + if (attrs.digits) { + digits = JSON.parse(attrs.digits); + } else if (attrs.options.digits) { + digits = attrs.options.digits; + } else if (Array.isArray(field.digits)) { + digits = field.digits; + } return { inputType: attrs.options.type, step: attrs.options.step, - // Sadly, digits param was available as an option and an attr. - // The option version could be removed with some xml refactoring. - digits: (attrs.digits ? JSON.parse(attrs.digits) : attrs.options.digits) || field.digits, + digits, placeholder: attrs.placeholder, }; }; diff --git a/addons/web/static/src/views/fields/float_toggle/float_toggle_field.js b/addons/web/static/src/views/fields/float_toggle/float_toggle_field.js index 23200d00022..4b5e15db9f0 100644 --- a/addons/web/static/src/views/fields/float_toggle/float_toggle_field.js +++ b/addons/web/static/src/views/fields/float_toggle/float_toggle_field.js @@ -48,8 +48,16 @@ FloatToggleField.supportedTypes = ["float"]; FloatToggleField.isEmpty = () => false; FloatToggleField.extractProps = ({ attrs, field }) => { + let digits; + if (attrs.digits) { + digits = JSON.parse(attrs.digits); + } else if (attrs.options.digits) { + digits = attrs.options.digits; + } else if (Array.isArray(field.digits)) { + digits = field.digits; + } return { - digits: (attrs.digits ? JSON.parse(attrs.digits) : attrs.options.digits) || field.digits, + digits, range: attrs.options.range, factor: attrs.options.factor, disableReadOnly: attrs.options.force_button || false, diff --git a/addons/web/static/src/views/fields/percentage/percentage_field.js b/addons/web/static/src/views/fields/percentage/percentage_field.js index 99f74697098..84649231e16 100644 --- a/addons/web/static/src/views/fields/percentage/percentage_field.js +++ b/addons/web/static/src/views/fields/percentage/percentage_field.js @@ -42,8 +42,16 @@ PercentageField.displayName = _lt("Percentage"); PercentageField.supportedTypes = ["integer", "float"]; PercentageField.extractProps = ({ attrs, field }) => { + let digits; + if (attrs.digits) { + digits = JSON.parse(attrs.digits); + } else if (attrs.options.digits) { + digits = attrs.options.digits; + } else if (Array.isArray(field.digits)) { + digits = field.digits; + } return { - digits: (attrs.digits ? JSON.parse(attrs.digits) : attrs.options.digits) || field.digits, + digits, placeholder: attrs.placeholder, }; }; diff --git a/addons/web/static/src/views/fields/stat_info/stat_info_field.js b/addons/web/static/src/views/fields/stat_info/stat_info_field.js index 2bc1e524239..bba74cc8a03 100644 --- a/addons/web/static/src/views/fields/stat_info/stat_info_field.js +++ b/addons/web/static/src/views/fields/stat_info/stat_info_field.js @@ -33,10 +33,18 @@ StatInfoField.supportedTypes = ["float", "integer", "monetary"]; StatInfoField.isEmpty = () => false; StatInfoField.extractProps = ({ attrs, field }) => { + let digits; + if (attrs.digits) { + digits = JSON.parse(attrs.digits); + } else if (attrs.options.digits) { + digits = attrs.options.digits; + } else if (Array.isArray(field.digits)) { + digits = field.digits; + } return { labelField: attrs.options.label_field, noLabel: archParseBoolean(attrs.nolabel), - digits: (attrs.digits ? JSON.parse(attrs.digits) : attrs.options.digits) || field.digits, + digits, }; }; diff --git a/addons/web/static/tests/views/fields/float_field_tests.js b/addons/web/static/tests/views/fields/float_field_tests.js index 478825efa80..5cdfd133ade 100644 --- a/addons/web/static/tests/views/fields/float_field_tests.js +++ b/addons/web/static/tests/views/fields/float_field_tests.js @@ -453,4 +453,27 @@ QUnit.module("Fields", (hooks) => { target.querySelectorAll(".o_field_widget[name=float_field] input")[1].value ); }); + + QUnit.test("float field with digits=0", async function (assert) { + // This isn't in the orm documentation, so it shouldn't be supported, but + // people do it and thus now we need to support it. + // Historically, it behaves like "no digits attribute defined", so it + // fallbacks on a precision of 2 digits. + // We will change that in master s.t. we do not round anymore in that case. + serverData.models.partner.fields.float_field.digits = 0; + + await makeView({ + type: "form", + serverData, + resModel: "partner", + resId: 1, + arch: '
', + }); + + assert.strictEqual( + target.querySelector(".o_field_float input").value, + "0.36", + "should contain a number rounded to 1 decimal" + ); + }); });