[FIX] web: prevent empty json field from passing the required check
Steps to reproduce ================== - Enable analytic accounting - Go to customer invoices - Open a record - Open studio - Click on the Invoice lines > Edit list view - Set the analytic field as required - Close studio - Create a new record - Add a new line - Click on the analytic field - Close the popup - Save the record => Even though we didn't set a value for the field, it is saved Cause of the issue ================== The actual field value is an empty object. The validity of a field is checked here [0]. An empty object is considered a truthy value. When setting the required attribute directly on the python field declaration, an empty object does not pass the check Solution ======== Add a specific check for json fields. When the value is either false (not set) or an empty object, the field is considered invalid. --- [0]: https://github.com/odoo/odoo/blob/23f01c533512cbfb33e90509e22cd3c3c4f99d40/addons/web/static/src/views/basic_relational_model.js#L284 opw-3659763 closes odoo/odoo#150677 X-original-commit: 51b538b3f678298f27bbbf458de5696706c18349 Signed-off-by: Francois Georis (fge) <fge@odoo.com> Signed-off-by: Hubert Van De Walle <huvw@odoo.com>
This commit is contained in:
@@ -402,6 +402,15 @@ export class Record extends DataPoint {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "json": {
|
||||
if (
|
||||
this._isRequired(fieldName) &&
|
||||
(!this.data[fieldName] || !Object.keys(this.data[fieldName]).length)
|
||||
) {
|
||||
unsetRequiredFields.push(fieldName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (!this.data[fieldName] && this._isRequired(fieldName)) {
|
||||
unsetRequiredFields.push(fieldName);
|
||||
|
||||
@@ -55,6 +55,7 @@ const DEFAULT_FIELD_VALUES = {
|
||||
selection: false,
|
||||
reference: false,
|
||||
properties: [],
|
||||
json: false,
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -55,6 +55,7 @@ import { Field } from "@web/views/fields/field";
|
||||
import { IntegerField } from "@web/views/fields/integer/integer_field";
|
||||
import { useSpecialData } from "@web/views/fields/relational_utils";
|
||||
import { X2ManyField, x2ManyField } from "@web/views/fields/x2many/x2many_field";
|
||||
import { standardFieldProps } from "@web/views/fields/standard_field_props";
|
||||
import { FormController } from "@web/views/form/form_controller";
|
||||
import { companyService } from "@web/webclient/company_service";
|
||||
|
||||
@@ -14541,4 +14542,38 @@ QUnit.module("Views", (hooks) => {
|
||||
".modal:not(.o_inactive_modal) .modal-footer button[name='someothername']"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("an empty json object does not pass the required check", async function (assert) {
|
||||
assert.expect(3);
|
||||
serverData.models.partner.fields.json_field = { type: "json" };
|
||||
class JsonField extends Component {
|
||||
onChange(ev) {
|
||||
this.props.record.update({ [this.props.name]: JSON.parse(ev.target.value) });
|
||||
}
|
||||
}
|
||||
JsonField.props = standardFieldProps;
|
||||
JsonField.supportedTypes = ["json"];
|
||||
JsonField.template = xml`<span><input t-on-change="onChange"/></span>`;
|
||||
|
||||
fieldRegistry.add("json", { component: JsonField });
|
||||
const form = await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
arch: `<form><field name="json_field" widget="json" required="1"/></form>`,
|
||||
});
|
||||
|
||||
patchWithCleanup(form.env.services.notification, {
|
||||
add: (message, params) => {
|
||||
assert.strictEqual(message.toString(), "<ul><li>json_field</li></ul>");
|
||||
assert.deepEqual(params, { title: "Invalid fields: ", type: "danger" });
|
||||
},
|
||||
});
|
||||
await editInput(target, ".o_field_widget[name=json_field] input", "{}")
|
||||
await clickSave(target);
|
||||
assert.hasClass(
|
||||
target.querySelector(".o_field_widget[name=json_field]"),
|
||||
"o_field_invalid"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user