[FIX] web: handle float fields with digits=0

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 <mcm@odoo.com>
This commit is contained in:
Aaron Bohy
2022-12-08 00:43:08 +01:00
parent ef41ffbb45
commit 5a5c2dbbf8
5 changed files with 61 additions and 6 deletions
@@ -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,
};
};
@@ -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,
@@ -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,
};
};
@@ -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,
};
};
@@ -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: '<form><field name="float_field"/></form>',
});
assert.strictEqual(
target.querySelector(".o_field_float input").value,
"0.36",
"should contain a number rounded to 1 decimal"
);
});
});