diff --git a/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js b/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js
index 9d3a2a798c7..601d6843322 100644
--- a/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js
+++ b/addons/web/static/src/views/fields/many2many_tags/many2many_tags_field.js
@@ -222,10 +222,9 @@ export const many2ManyTagsField = {
return relatedFields;
},
extractProps({ attrs, options, string }, dynamicInfo) {
+ const hasCreatePermission = attrs.can_create ? evaluateBooleanExpr(attrs.can_create) : true;
const noCreate = Boolean(options.no_create);
- const canCreate = noCreate
- ? false
- : attrs.can_create && evaluateBooleanExpr(attrs.can_create);
+ const canCreate = noCreate ? false : hasCreatePermission;
const noQuickCreate = Boolean(options.no_quick_create);
const noCreateEdit = Boolean(options.no_create_edit);
return {
diff --git a/addons/web/static/src/views/fields/many2one/many2one_field.js b/addons/web/static/src/views/fields/many2one/many2one_field.js
index 5dfd143c011..97f4609d252 100644
--- a/addons/web/static/src/views/fields/many2one/many2one_field.js
+++ b/addons/web/static/src/views/fields/many2one/many2one_field.js
@@ -366,13 +366,14 @@ export const many2OneField = {
],
supportedTypes: ["many2one"],
extractProps({ attrs, context, decorations, options, string }, dynamicInfo) {
- const canCreate =
- options.no_create ? false : attrs.can_create && evaluateBooleanExpr(attrs.can_create);
+ const hasCreatePermission = attrs.can_create ? evaluateBooleanExpr(attrs.can_create) : true;
+ const hasWritePermission = attrs.can_write ? evaluateBooleanExpr(attrs.can_write) : true;
+ const canCreate = options.no_create ? false : hasCreatePermission
return {
placeholder: attrs.placeholder,
canOpen: !options.no_open,
canCreate,
- canWrite: attrs.can_write && evaluateBooleanExpr(attrs.can_write),
+ canWrite: hasWritePermission,
canQuickCreate: canCreate && !options.no_quick_create,
canCreateEdit: canCreate && !options.no_create_edit,
context: context,
diff --git a/addons/web/static/tests/mock_server_tests.js b/addons/web/static/tests/mock_server_tests.js
index e7744a2d142..87dfcd28ab4 100644
--- a/addons/web/static/tests/mock_server_tests.js
+++ b/addons/web/static/tests/mock_server_tests.js
@@ -1457,4 +1457,53 @@ QUnit.module("MockServer", (hooks) => {
});
assert.deepEqual(result.value, { foo: 0 });
});
+
+ QUnit.test(
+ "access rights attributes are present on an editable many2one field",
+ async function (assert) {
+ data.views = {
+ "bar,10001,form": `
`,
+ "bar,10001,search": ``,
+ };
+
+ const expectedForm = ``;
+ const mockServer = new MockServer(data);
+ const { views } = mockServer.mockGetViews("bar", {
+ views: [[10001, "form"]],
+ options: {},
+ });
+ assert.deepEqual(views.form.arch, expectedForm);
+ }
+ );
+
+ QUnit.test(
+ "access rights attributes are missing on an editable many2one field",
+ async function (assert) {
+ // The access rights attributes should be present,
+ // but are actually missing when a field definition is readonly and readonly=0 is on the view.
+ // @see the commit description for more details.
+
+ data.models.bar.fields.partner_id.readonly = true;
+ data.views = {
+ "bar,10001,form": ``,
+ "bar,10001,search": ``,
+ };
+
+ const expectedForm = ``;
+ const mockServer = new MockServer(data);
+ const { views } = mockServer.mockGetViews("bar", {
+ views: [[10001, "form"]],
+ options: {},
+ });
+ assert.deepEqual(views.form.arch, expectedForm);
+ }
+ );
});
diff --git a/addons/web/static/tests/views/fields/many2one_field_tests.js b/addons/web/static/tests/views/fields/many2one_field_tests.js
index e9ba4b51088..e6a69015de9 100644
--- a/addons/web/static/tests/views/fields/many2one_field_tests.js
+++ b/addons/web/static/tests/views/fields/many2one_field_tests.js
@@ -3239,6 +3239,31 @@ QUnit.module("Fields", (hooks) => {
);
});
+ QUnit.test("no_quick_create option on a many2one when can_create is absent", async function (assert) {
+ serverData.models.partner.fields.product_id.readonly = true;
+ await makeView({
+ type: "form",
+ resModel: "partner",
+ serverData,
+ arch: `
+ `,
+ });
+ await editInput(target, ".o_field_many2one input", "new partner");
+ assert.containsOnce(
+ target,
+ ".ui-autocomplete .o_m2o_dropdown_option",
+ "Dropdown should be opened and have only one item"
+ );
+ assert.hasClass(
+ target.querySelector(".ui-autocomplete .o_m2o_dropdown_option"),
+ "o_m2o_dropdown_option_create_edit"
+ );
+ });
+
QUnit.test("can_create and can_write option on a many2one", async function (assert) {
serverData.models.product.options = {
can_create: "false",
diff --git a/addons/web/static/tests/views/fields/reference_field_tests.js b/addons/web/static/tests/views/fields/reference_field_tests.js
index 4a14d3d757b..a1ee0c7b9cc 100644
--- a/addons/web/static/tests/views/fields/reference_field_tests.js
+++ b/addons/web/static/tests/views/fields/reference_field_tests.js
@@ -258,6 +258,28 @@ QUnit.module("Fields", (hooks) => {
);
});
+ QUnit.test("ReferenceField respects no_quick_create", async function (assert) {
+ await makeView({
+ type: "form",
+ resModel: "partner",
+ serverData,
+ arch: ``,
+ });
+
+ await editSelect(target, "select", "partner");
+ await click(target, ".o_field_widget[name='reference'] input");
+ await editInput(target, ".o_field_widget[name='reference'] input", "new partner");
+ assert.containsOnce(
+ target,
+ ".ui-autocomplete .o_m2o_dropdown_option",
+ "Dropdown should be opened and have only one item"
+ );
+ assert.hasClass(
+ target.querySelector(".ui-autocomplete .o_m2o_dropdown_option"),
+ "o_m2o_dropdown_option_create_edit"
+ );
+ });
+
QUnit.test("ReferenceField in modal readonly mode", async function (assert) {
serverData.models.partner.records[0].p = [2];
serverData.models.partner.records[1].trululu = 1;