Skip to content

Conversation

@dnplkndll
Copy link

No description provided.

clementmbr and others added 30 commits February 5, 2025 11:48
New organization :

- attribute_set (former base_custom_attribute)
- product_attribute_set (former pim_custom_attribute but without menus)
- pim (The "PIM application" former pim_base)
- pim_attrubute_set (depends on product_attribute_set and adds menus in
the PIM application)
And small FIX in _build_attribute_field()
…d attribute_set

[CHG] add required columns on attributes on attribute set form view

attribute_set 13.0.1.0.1
[UPD] README.rst

[UPD] README.rst

[ADD] icon.png

Apply dotfiles

[UPD] Update attribute_set.pot

attribute_set 14.0.1.0.1

[UPD] README.rst

[IMP] update dotfiles [ci skip]
[UPD] Update attribute_set.pot

attribute_set 14.0.1.1.0
[UPD] Update attribute_set.pot

[UPD] README.rst
When you define an attribute as a select field and add a related model,
you have the option to "Load attribute options".

On this wizard, an "option_ids" dummy field is created via
fields_view_get.

This change deletes option_ids from create (once the options are created) and read
menu items are visible only for two levels
[UPD] Update attribute_set.pot

[UPD] README.rst

[UPD] README.rst
…ss data (tree/search...)

Use get_view() to get the view_type directly. Moreover, this will allow to test it through
odoo.tests.Form().

Add attribute_set_id field in test form (as it should be included in inherited views
If user is not in the base.group_erp_manager group, the value_ref field
selection function will be computed without access rights on ir.model.
So, hide the field for users not in that group.
Add all the attributes defined for the model into the list of fields to load to display the form view. Wihout this change a JS error occurs when displaying the form view of a x2many field for a model defining attributes. The origin of the error comes from the the get_views method which is called for the type 'form' only. In this case it's important to add all the custom attributes to the list of fields defined on the model for the view. When the same method is called without restriction it will load all the views. Since odoo include all the fields defined on the model for the search view, the error doesn't occur when using the form view from a menu action.
@kobros-tech kobros-tech mentioned this pull request Feb 10, 2025
2 tasks
@dnplkndll dnplkndll force-pushed the 18.0-mig-attribute_set branch from 75801f6 to 5eb64de Compare February 10, 2025 16:44
@kobros-tech kobros-tech force-pushed the 18.0-mig-attribute_set branch 2 times, most recently from fb0f45c to 45cf3a9 Compare February 11, 2025 01:16
@kobros-tech kobros-tech force-pushed the 18.0-mig-attribute_set branch 3 times, most recently from 3e78e2b to 64e9353 Compare February 23, 2025 19:59
string="Attribute Nature",
required=True,
default="custom",
store=True,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
store=True,

no need

ast.literal_eval(self.domain)
except ValueError:
raise ValidationError(
_(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_(
self.env. _(

# context since 17.0 will be dropped in views
# unless we suffix it's key with _view_ref
"context": {"attribute_id_view_ref": self.id},
"name": _("Options Wizard"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"name": _("Options Wizard"),
"name": self.env._("Options Wizard"),

"""Delete outdated attribute's field values on existing records."""
self.ensure_one()
custom_field = self.name
for obj in self.env[self.model].search([]):
Copy link

@xaviedoanhduy xaviedoanhduy Feb 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use the filtered function to reduce nesting of if and for statements?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you write the code and I apply?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see filtered method is great, but also regarding migration we focus on the scope.

but reducing syntax and improving it is better to be in it's own [IMP] PR, right?

Comment on lines 416 to 462
def write(self, vals):
# Prevent from changing Attribute's type
if "attribute_type" in list(vals.keys()):
if self.search_count(
[
("attribute_type", "!=", vals["attribute_type"]),
("id", "in", self.ids),
]
):
raise ValidationError(
_(
"Can't change the type of an attribute. "
"Please create a new one."
)
)
else:
vals.pop("attribute_type")
# Prevent from changing relation_model_id for multiselect Attributes
# as the values of the existing many2many Attribute fields won't be
# deleted if changing relation_model_id
if "relation_model_id" in list(vals.keys()):
if self.search_count(
[
("relation_model_id", "!=", vals["relation_model_id"]),
("id", "in", self.ids),
]
):
raise ValidationError(
_(
"""Can't change the attribute's Relational Model in order to
avoid conflicts with existing objects using this attribute.
Please create a new one."""
)
)
# Prevent from changing 'Serialized'
if "serialized" in list(vals.keys()):
if self.search_count(
[("serialized", "!=", vals["serialized"]), ("id", "in", self.ids)]
):
raise ValidationError(
_(
"""It is not allowed to change the boolean 'Serialized'.
A serialized field can not be change to non-serialized \
and vice versa."""
)
)
# Set the new values to self
res = super().write(vals)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def write(self, vals):
# Prevent from changing Attribute's type
if "attribute_type" in list(vals.keys()):
if self.search_count(
[
("attribute_type", "!=", vals["attribute_type"]),
("id", "in", self.ids),
]
):
raise ValidationError(
_(
"Can't change the type of an attribute. "
"Please create a new one."
)
)
else:
vals.pop("attribute_type")
# Prevent from changing relation_model_id for multiselect Attributes
# as the values of the existing many2many Attribute fields won't be
# deleted if changing relation_model_id
if "relation_model_id" in list(vals.keys()):
if self.search_count(
[
("relation_model_id", "!=", vals["relation_model_id"]),
("id", "in", self.ids),
]
):
raise ValidationError(
_(
"""Can't change the attribute's Relational Model in order to
avoid conflicts with existing objects using this attribute.
Please create a new one."""
)
)
# Prevent from changing 'Serialized'
if "serialized" in list(vals.keys()):
if self.search_count(
[("serialized", "!=", vals["serialized"]), ("id", "in", self.ids)]
):
raise ValidationError(
_(
"""It is not allowed to change the boolean 'Serialized'.
A serialized field can not be change to non-serialized \
and vice versa."""
)
)
# Set the new values to self
res = super().write(vals)
def write(self, vals):
def _check_field_change(field, error_message):
"""Helper function to check if a field is being changed and raise an error if so."""
if field in vals:
if self.search_count([(field, "!=", vals[field]), ("id", "in", self.ids)]):
raise ValidationError(self.env._(error_message))
else:
vals.pop(field)
# Prevent changing Attribute's type
_check_field_change(
"attribute_type",
"Can't change the type of an attribute. Please create a new one.",
)
# Prevent changing relation_model_id for multiselect Attributes
_check_field_change(
"relation_model_id",
"""Can't change the attribute's Relational Model to avoid conflicts with
existing objects using this attribute. Please create a new one.""",
)
# Prevent changing 'Serialized'
_check_field_change(
"serialized",
"""It is not allowed to change the boolean 'Serialized'.
A serialized field cannot be changed to non-serialized and vice versa.""",
)
# Set the new values to self
res = super().write(vals)

This is just a small suggestion on how to reuse another function, you can split it out and besides the labels of the fields like Serialized, Relational Model and type of an attribute should come from the fields (and respect eventual translations).
hint: you can refer to this forum: https://www.odoo.com/forum/help-1/get-the-value-of-string-in-fields-150616

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, in fact I respect how you tend to minimize and organize code.

I am afraid if this good idea can apply during migration as I see migration tends to focus on migrating changes requied in new versions so it can be easy to review and catch errors in the process.

But, I like improvements be applied just after migration in the name of reducing code or optimizing it.

Comment on lines 32 to 35
if node.get("attrs"):
modifiers.update(safe_eval(node.get("attrs")))

if node.get("states"):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML attributes attrs and states are no longer used, and should be replaced by their equivalent Python expression under invisible, required and/or readonly attributes. Example: attrs="{'invisible': [('name', '=', 'red')]} is converted to invisible="name == 'red'". Full explanation and more examples at

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good observation, thanks!

@xaviedoanhduy
Copy link

xaviedoanhduy commented Mar 4, 2025

I’m comparing the UI between versions 16.0 and 18.0, and in this PR, I noticed you mentioned some improvements in here. I’m looking forward to them, and it would be great if these enhancements also made the UI more user-friendly.

  • version 16.0
    image

  • version 18.0
    image

@dnplkndll
Copy link
Author

I wondered if feasible to use:

image

from:
odoo/odoo#132578

@xaviedoanhduy
Copy link

xaviedoanhduy commented Mar 4, 2025

I wondered if feasible to use:

hi @dnplkndll, do you mean replace Attribute why native odoo Properties? it could make sense in the future, but currently odoo Properties are not fully equivalent. Because some fields such as Binary type and Required attribute do not currently appear in Properties. see https://www.odoo.com/documentation/18.0/applications/productivity/knowledge/properties.html

ALLOWED_TYPES = (
       # standard types
       'boolean', 'integer', 'float', 'char', 'date', 'datetime',
       # relational like types
       'many2one', 'many2many', 'selection', 'tags',
       # UI types
       'separator',
   )

detail in: https://github.com/odoo/odoo/blob/0f731fd28c921a92e2cab4842cd0770242ff69c0/odoo/fields.py#L3508-L3515

@xaviedoanhduy
Copy link

xaviedoanhduy commented Mar 4, 2025

lost display of Model field

image

image

@dnplkndll
Copy link
Author

hi @dnplkndll, do you mean replace Attribute why native odoo Properties? it could make sense in the future, but currently odoo Properties are not fully equivalent. Because some fields such as Binary type and Required attribute do not currently appear in Properties.

I not completely. but perhaps the similar UI to place and group them? set properties like visible in search and filter on the website. probably would just cause more required changes on upstream changes though

@kobros-tech
Copy link

@xaviedoanhduy

can you have a look?

@kobros-tech
Copy link

@xaviedoanhduy

is there any remaining comments?

Comment on lines +52 to +53
"title": _("Error!"),
"message": _(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"title": _("Error!"),
"message": _(
"title": self.env._("Error!"),
"message": self.env._(


if len(placeholder) != 1:
raise ValidationError(
_(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_(
self.env._(

<field name="model">attribute.option</field>
<field name="priority" eval="6" />
<field name="arch" type="xml">
<form string="Attribute Option" col="6">
Copy link

@xaviedoanhduy xaviedoanhduy Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<form string="Attribute Option" col="6">
<form string="Attribute Option" col="6">

What does the col attribute do here?
btw I see some migrations also remove the string attribute on form view, it might be an optional you can check it out here: OCA/account-financial-tools@c581dba

@xaviedoanhduy
Copy link

xaviedoanhduy commented Jun 26, 2025

comments #192 (comment) and #192 (comment) are still pending

@kobros-tech
Copy link

comments #192 (comment) and #192 (comment) are still pending

what is the error in these two comments?

@xaviedoanhduy
Copy link

what is the error in these two comments?

  1. in [18.0][MIG] attribute_set: Migration to 18.0 #192 (comment):
  • You can see that in version 16.0 they are just grouped in 1 column (probably 1 group) in a straight line but in version 18.0 it has been split into 3 groups and looks quite weird.
image
  1. in [18.0][MIG] attribute_set: Migration to 18.0 #192 (comment):
  • You see that in version 18.0, the Model field has been lost on the form view.
image

@kobros-tech kobros-tech force-pushed the 18.0-mig-attribute_set branch from 0a28833 to 54eef80 Compare August 25, 2025 18:53
@kobros-tech
Copy link

kobros-tech commented Aug 25, 2025

@xaviedoanhduy

for the model_id field, thanks for clarifying I put it is its correct place!

but for changing the UI and grouping fields I had to do so because of some UI errors and the fields were so many for be traced in one row.

@kobros-tech kobros-tech force-pushed the 18.0-mig-attribute_set branch from 54eef80 to 56d085e Compare August 25, 2025 18:59
@kobros-tech kobros-tech force-pushed the 18.0-mig-attribute_set branch from 56d085e to bac9366 Compare August 25, 2025 19:02
@kobros-tech
Copy link

@xaviedoanhduy

Now I squashed all commits so someone can see changes properly, the module is huge and the changes are many.

I hope we finish it with the optimum quality, thanks!

@xaviedoanhduy
Copy link

@xaviedoanhduy

Now I squashed all commits so someone can see changes properly, the module is huge and the changes are many.

I hope we finish it with the optimum quality, thanks!

hi, @kobros-tech
I noticed that the [MIG] attribute_set: Migration to 18.0 commit includes a large number of changes, including some that don’t seem directly related to the scope of this PR. It looks like they might be attempts to improve or extend certain features, but this makes it harder for me and other reviewers to fully evaluate the migration itself.

In my opinion, a migration PR should focus strictly on updating the code to align with upstream changes. Any additional improvements or new features would be better handled in a separate PR or commit, so that they can be reviewed and discussed more easily.

Thanks a lot for the effort you’ve put into this!

@kobros-tech
Copy link

@xaviedoanhduy

maybe you are the best if you introduce a better migration PR based on this one or the previous versions as I know you are a very good developer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.