| REPOSITORY | |
|---|---|
| REPOSITORY | OCA/product-configurator |
| GIT | |
| GIT | https://github.com/OCA/product-configurator.git |
| GIT FOLDER | |
| GIT FOLDER | https://github.com/OCA/product-configurator/tree/18.0/product_configurator |
| VERSION | |
| VERSION | 1.0.0 |
| CATEGORY | |
| CATEGORY | Generic Modules/Base |
| LICENSE | |
| LICENSE | AGPL-3 |
| APPLICATION | |
| APPLICATION | Yes |
| AUTO-INSTALLABLE | |
| AUTO-INSTALLABLE | No |
| AUTHORS | |
| AUTHORS | Odoo Community Association (OCA), Pledra |
| MAINTAINERS | |
| MAINTAINERS | Odoo Community Association (OCA), Pledra |
| COMMITTERS | |
| COMMITTERS | Ruchir Shukla, Weblate, OCA-git-bot, oca-ci |
| WEBSITE | |
| WEBSITE | https://github.com/OCA/product-configurator |
| LAST TRACKING UPDATE | |
| LAST TRACKING UPDATE | 2026-07-06 19:30:08 |
| ODOO DEPENDENCIES | |
| ODOO DEPENDENCIES |
odoo/odoo: - account - base_setup - base - web - onboarding - product - bus - web_tour - html_editor - uom - analytic - portal - web_editor - http_routing - auth_signup - digest - resource - stock - barcodes_gs1_nomenclature - barcodes |
| PYTHON DEPENDENCIES | |
| PYTHON DEPENDENCIES |
mako |
| SYSTEM DEPENDENCIES | |
| SYSTEM DEPENDENCIES | Not have |
| DESCRIPTION | |
| DESCRIPTION | This module has all the mechanics to support product configuration. It serves as a base dependency for configuration interfaces. |
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
config_step_form_view |
product.configurator.config.step.form | product.config.step | form | New |
config_step_tree_view |
product.configurator.config.step.tree | product.config.step | form | New |
configurator_settings_view_form |
res.config.settings.view.form.inherit.sale | res.config.settings | xpath | Inherits base.res_config_settings_view_form |
product_attribute_form_view |
product.attribute.form.view | product.attribute | xpath | Inherits product.product_attribute_view_form |
product_attribute_tree_view |
product.config.product.attribute.tree | product.attribute | xpath | Inherits product.attribute_tree_view |
product_attribute_value_form_view |
product.config.product.attribute.value.form.view | product.attribute.value | form | New |
product_attribute_value_list |
product.attribute.value.list.inherit | product.attribute.value | xpath | Inherits product.product_attribute_value_list |
product_config_domain_form_view |
product.configurator.domain.form | product.config.domain | form | New |
product_config_domain_form_view_template |
product.configurator.domain.form.template | product.config.domain | form | New |
product_config_session_form_view |
product.config.session.form | product.config.session | form | New |
product_config_session_tree_view |
product.config.session.tree | product.config.session | list | New |
product_configurator_form |
product.configurator | product.configurator | form | New |
product_form_view_custom_vals_inherit |
product.configurator.form.view.custom.vals | product.product | xpath | Inherits product.product_normal_form_view |
product_kanban_view_inherited |
Product Kanban | product.product | xpath | Inherits product.product_kanban_view |
product_template_attribute_line_form_config |
product.template.attribute.line.form | product.template.attribute.line | xpath | Inherits product.product_template_attribute_line_form |
product_template_attribute_value_view_form_weight_extra |
product.template.attribute.value.view.form.weight.extra | product.template.attribute.value | xpath | Inherits product.product_template_attribute_value_view_form |
product_template_attribute_value_view_tree_weight_extra |
product.template.attribute.value.view.tree.weight.extra | product.template.attribute.value | xpath | Inherits product.product_template_attribute_value_view_tree |
product_template_form_view_config_inherited |
product.template.common.form | product.template | xpath | Inherits product.product_template_form_view |
product_template_kanban_view_inherited |
Product.template.product.kanban | product.template | xpath | Inherits product.product_template_kanban_view |
product_template_only_form_view_inherited |
product.configurator.product.template.form | product.template | xpath | Inherits product.product_template_only_form_view |
product_template_search_view |
product.configurator.product.template.search.view | product.template | xpath | Inherits product.product_template_search_view |
product_variant_easy_edit_view_inherit |
product.product.view.form.easy | product.product | xpath | Inherits product.product_variant_easy_edit_view |
template_view_tree_configurable |
product.template.product.tree | product.template | xpath | Inherits product.product_template_tree_view |
No new fields.
Public methods (0)No public methods.
active
Boolean
default=True
help='By unchecking the active field you can disable a attribute without deleting it'
custom_type
Selection
help='The type of the custom field generated in the frontend'
selection=CUSTOM_TYPES
string='Field Type'
description
Text
translate=True
image
Binary
max_val
Integer
help='Maximum value allowed'
string='Max Value'
min_val
Integer
help='Minimum value allowed'
string='Min Value'
multi
Boolean
help='Allow selection of multiple values for this attribute?'
required
Boolean
default=True
help='Determines the required value of this attribute though it can be change on the template level'
search_ok
Boolean
help='When checking for variants with the same configuration, do we include this field in the search?'
string='Searchable'
uom_id
Many2one → uom.uom
comodel_name='uom.uom'
string='Unit of Measure'
val_custom
Boolean
help='Allow custom value for this attribute?'
string='Custom Value'
check_searchable_field(self)
copy(self, default=None)
onchange_custom_type(self)
onchange_val_custom_field(self)
validate_custom_val(self, val)
active
Boolean
default=True
help='By unchecking the active field you can disable a attribute value without deleting it'
image
Binary
attachment=True
help='Attribute value image (Display on website for radio buttons)'
product_id
Many2one → product.product
comodel_name='product.product'
copy(self, default=None)
get_attribute_value_extra_prices(self, product_tmpl_id, pt_attr_value_ids, pricelist=None)
name_search(self, name='', args=None, operator='ilike', limit=100)
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
related='value_id.attribute_id'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
product_value_ids
Many2many → product.attribute.value
column1='product_val_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
compute='_compute_get_value_id'
relation='product_attr_values_attr_values_rel'
store=True
sequence
Integer
default=10
value_id
Many2one → product.attribute.value
comodel_name='product.attribute.value'
required=True
string='Attribute Value'
value_ids
Many2many → product.attribute.value
column1='product_attribute_value_line_id'
column2='product_attribute_value_id'
comodel_name='product.attribute.value'
relation='product_attribute_value_product_attribute_value_line_rel'
string='Values Configuration'
No public methods.
domain_line_ids
One2many → product.config.domain.line
comodel_name='product.config.domain.line'
copy=True
inverse_name='domain_id'
required=True
string='Restrictions'
implied_ids
Many2many → product.config.domain
column1='domain_id'
column2='parent_id'
comodel_name='product.config.domain'
relation='product_config_domain_implied_rel'
string='Inherited'
name
Char
required=True
trans_implied_ids
Many2many → product.config.domain
column1='domain_id'
column2='parent_id'
comodel_name='product.config.domain'
compute=_get_trans_implied
string='Transitively inherits'
compute_domain(self)
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
domain=<expr>
required=True
string='Attribute'
condition
Selection
required=True
selection=_get_domain_conditions
domain_id
Many2one → product.config.domain
comodel_name='product.config.domain'
required=True
string='Rule'
operator
Selection
default='and'
required=True
selection=_get_domain_operators
string='Operators'
sequence
Integer
default=1
help='Set the order of operations for evaluation domain lines'
template_attribute_value_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_template_attribute_value_ids'
string='Template Attribute Values'
value_ids
Many2many → product.attribute.value
column1='line_id'
column2='attribute_id'
comodel_name='product.attribute.value'
relation='product_config_domain_line_attr_rel'
required=True
string='Values'
No public methods.
name
Char
required=True
translate=True
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product'
sequence
Integer
default=10
value_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
string='Configuration'
No public methods.
attr_line_val_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_attr_line_val_ids'
help="For normal attributes the values configured for the product can be selected.\nFor custom attributes the 'Custom' value can also be selected."
string='Allowed Attribute Values'
attribute_line_id
Many2one → product.template.attribute.line
comodel_name='product.template.attribute.line'
ondelete='cascade'
required=True
string='Attribute Line'
domain_id
Many2one → product.config.domain
comodel_name='product.config.domain'
required=True
string='Restrictions'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
sequence
Integer
default=10
template_attribute_ids
Many2many → product.attribute
comodel_name='product.attribute'
compute='_compute_template_attribute_ids'
string='Template Attributes'
value_ids
Many2many → product.attribute.value
column1='cfg_line_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
relation='cfg_line_attr_val_id_rel'
string='Values'
check_value_attributes(self)
onchange_attribute(self)
config_step
Char
string='Configuration Step ID'
config_step_name
Char
compute='_compute_config_step_name'
string='Configuration Step'
currency_id
Many2one → res.currency
comodel_name='res.currency'
compute='_compute_currency_id'
string='Currency'
custom_value_ids
One2many → product.config.session.custom.value
comodel_name='product.config.session.custom.value'
inverse_name='cfg_session_id'
string='Custom Values'
name
Char
readonly=True
string='Configuration Session Number'
price
Float
compute='_compute_cfg_price'
digits='Product Price'
store=True
product_id
Many2one → product.product
comodel_name='product.product'
name='Configured Variant'
ondelete='cascade'
product_preset_id
Many2one → product.product
comodel_name='product.product'
string='Preset'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
domain=[('config_ok', '=', True)]
required=True
string='Configurable Template'
state
Selection
default='draft'
required=True
selection=[('draft', 'Draft'), ('done', 'Done')]
user_id
Many2one → res.users
comodel_name='res.users'
required=True
string='User'
value_ids
Many2many → product.attribute.value
column1='cfg_session_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
relation='product_config_session_attr_values_rel'
weight
Float
compute='_compute_cfg_weight'
digits='Stock Weight'
action_confirm(self, product_id=None)
check_and_open_incomplete_step(self, value_ids=None, custom_value_ids=None)
check_attributes_configuration(self, attribute_line_ids, custom_vals, value_ids, final=True)
create(self, vals_list)
create_get_session(self, product_tmpl_id, parent_id=None, force_create=False, user_id=None)
create_get_variant(self, value_ids=None, custom_vals=None)
flatten_attribute_value_ids(self, value_ids)
flatten_val_ids(self, value_ids)
formatPrices(self, prices=None, dp='Product Price')
get_active_step(self)
get_adjacent_steps(self, value_ids=None, active_step_line_id=None)
get_all_step_lines(self, product_tmpl_id=None)
get_cfg_price(self, value_ids=None, custom_vals=None)
get_cfg_weight(self, value_ids=None, custom_vals=None)
get_child_specification(self, model, parent)
get_components_prices(self, prices, pricelist, value_ids=None)
get_config_image(self, value_ids=None, custom_vals=None, size=None)
get_custom_value_id(self)
get_extra_attribute_line_ids(self, product_template_id)
get_next_step(self, state, product_tmpl_id=False, value_ids=False, custom_value_ids=False)
get_onchange_specifications(self, model)
get_open_step_lines(self, value_ids=None)
get_session_search_domain(self, product_tmpl_id, state='draft', parent_id=None)
get_session_vals(self, product_tmpl_id, parent_id=None, user_id=None)
get_vals_to_write(self, values, model)
get_variant_search_domain(self, product_tmpl_id, value_ids=None)
get_variant_vals(self, value_ids=None, custom_vals=None, **kwargs)
search_session(self, product_tmpl_id, parent_id=None)
search_variant(self, value_ids=None, product_tmpl_id=None)
update_config(self, attr_val_dict=None, custom_val_dict=None)
update_session_configuration_value(self, vals, product_tmpl_id=None)
validate_configuration(self, value_ids=None, custom_vals=None, product_tmpl_id=False, final=True)
validate_domains_against_sels(self, domains, value_ids=None, custom_vals=None)
values_available(self, check_val_ids=None, value_ids=None, custom_vals=None, product_tmpl_id=None, product_template_attribute_line_id=None)
write(self, vals)
attachment_ids
Many2many → ir.attachment
column1='cfg_sesion_custom_val_id'
column2='attachment_id'
comodel_name='ir.attachment'
relation='product_config_session_custom_value_attachment_rel'
string='Attachments'
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
required=True
string='Attribute'
cfg_session_id
Many2one → product.config.session
comodel_name='product.config.session'
ondelete='cascade'
required=True
string='Session'
name
Char
compute='_compute_val_name'
readonly=True
store=True
value
Char
help='Custom value held as string'
check_custom_type(self)
eval(self)
unique_attribute(self)
name
Char
required=True
translate=True
No public methods.
attribute_line_ids
Many2many → product.template.attribute.line
column1='cfg_line_id'
column2='attr_id'
comodel_name='product.template.attribute.line'
relation='config_step_line_attr_id_rel'
string='Attribute Lines'
config_step_id
Many2one → product.config.step
comodel_name='product.config.step'
required=True
string='Configuration Step'
name
Char
related='config_step_id.name'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
sequence
Integer
default=10
No public methods.
attribute_line_ids
One2many → product.template.attribute.line
comodel_name='product.template.attribute.line'
compute='_compute_attr_lines'
readonly=True
store=False
string='Attributes'
config_session_id
Many2one → product.config.session
comodel_name='product.config.session'
ondelete='cascade'
required=True
string='Configuration Session'
config_step_ids
Many2many → product.config.step
column1='config_wiz_id'
column2='config_step_id'
comodel_name='product.config.step'
readonly=True
relation='product_config_config_steps_rel'
store=False
string='Configuration Steps'
product_id
Many2one → product.product
comodel_name='product.product'
help='Set only when re-configuring a existing variant'
readonly=True
string='Product Variant'
product_img
Binary
compute='_compute_cfg_image'
readonly=True
action_config_done(self)
action_next_step(self)
action_previous_step(self)
action_reset(self)
add_dynamic_fields(self, res, dynamic_fields, wiz)
apply_onchange_values(self, values, field_names, field_onchange)
create(self, vals_list)
fields_get(self, allfields=None, write_access=True, attributes=None)
get_field_default_attrs(self)
get_form_vals(self, dynamic_fields, domains, cfg_val_ids=None, product_tmpl_id=None, config_session_id=None, values=None)
get_onchange_domains(self, cfg_val_ids, product_tmpl_id=False, config_session_id=False)
get_onchange_vals(self, cfg_val_ids, config_session_id=None)
get_state_selection(self)
get_view(self, view_id=None, view_type='form', **options)
get_wizard_action(self, view_cache=False, wizard=None)
onchange(self, values: dict, field_names: <expr>, fields_spec: dict)
onchange_product_tmpl(self)
open_step(self, step)
read(self, fields=None, load='_classic_read')
write(self, vals)
config_name
Char
compute='_compute_config_name'
string='Configuration Name'
config_preset_ok
Boolean
string='Is Preset'
weight
Float
compute='_compute_product_weight'
inverse='_inverse_product_weight'
search='_search_product_weight'
store=False
weight_dummy
Float
digits='Stock Weight'
string='Manual Weight'
weight_extra
Float
compute='_compute_product_weight_extra'
check_config_user_access(self, mode)
create(self, vals_list)
reconfigure_product(self)
unlink(self)
write(self, vals)
attribute_line_val_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_template_attr_vals'
store=False
attribute_value_line_ids
One2many → product.attribute.value.line
comodel_name='product.attribute.value.line'
copy=True
inverse_name='product_tmpl_id'
string='Attribute Value Lines'
config_image_ids
One2many → product.config.image
comodel_name='product.config.image'
copy=True
inverse_name='product_tmpl_id'
string='Configuration Images'
config_line_ids
One2many → product.config.line
comodel_name='product.config.line'
copy=False
inverse_name='product_tmpl_id'
string='Attribute Dependencies'
config_ok
Boolean
string='Can be Configured'
config_step_line_ids
One2many → product.config.step.line
comodel_name='product.config.step.line'
copy=False
inverse_name='product_tmpl_id'
string='Configuration Lines'
mako_tmpl_name
Text
copy=True
help='Generate Name based on Mako Template'
string='Variant name'
weight
Float
compute='_compute_weight'
inverse='_set_weight'
search='_search_weight'
store=False
weight_dummy
Float
digits='Stock Weight'
help='Manual setting of product template weight'
string='Manual Weight'
check_attr_value_ids(self)
check_config_user_access(self)
configure_product(self)
copy(self, default=None)
create(self, vals_list)
create_config_wizard(self, model_name='product.configurator', extra_vals=None, click_next=True)
toggle_config(self)
unlink(self)
write(self, vals)
custom
Boolean
help='Allow custom values for this attribute?'
default_val
Many2one → product.attribute.value
comodel_name='product.attribute.value'
invisible_condition
Char
compute='_compute_attribute_condition'
store=True
multi
Boolean
help='Allow selection of multiple values for this attribute?'
readonly_condition
Char
compute='_compute_attribute_condition'
store=True
required
Boolean
help='Is this attribute required?'
required_condition
Char
compute='_compute_attribute_condition'
store=True
sequence
Integer
default=10
get_dependencies(self)
get_invisible_condition(self, config_steps)
get_readonly_condition(self, config_steps, dependencies)
get_required_condition(self, config_steps, dependencies)
onchange_attribute(self)
onchange_values(self)
weight_extra
Float
digits='Stock Weight'
string='Attribute Weight Extra'
No public methods.
| REPOSITORY | |
|---|---|
| REPOSITORY | OCA/product-configurator |
| GIT | |
| GIT | https://github.com/OCA/product-configurator.git |
| GIT FOLDER | |
| GIT FOLDER | https://github.com/OCA/product-configurator/tree/17.0/product_configurator |
| VERSION | |
| VERSION | 1.0.2 |
| CATEGORY | |
| CATEGORY | Generic Modules/Base |
| LICENSE | |
| LICENSE | AGPL-3 |
| APPLICATION | |
| APPLICATION | Yes |
| AUTO-INSTALLABLE | |
| AUTO-INSTALLABLE | No |
| AUTHORS | |
| AUTHORS | Odoo Community Association (OCA), Pledra |
| MAINTAINERS | |
| MAINTAINERS | Odoo Community Association (OCA), Pledra |
| COMMITTERS | |
| COMMITTERS | Ruchir Shukla, Weblate, OCA-git-bot, Simone Orsi, oca-ci |
| WEBSITE | |
| WEBSITE | https://github.com/OCA/product-configurator |
| LAST TRACKING UPDATE | |
| LAST TRACKING UPDATE | 2026-07-06 19:20:02 |
| ODOO DEPENDENCIES | |
| ODOO DEPENDENCIES |
odoo/odoo: - account - base_setup - base - web - onboarding - product - bus - web_tour - uom - analytic - portal - web_editor - http_routing - auth_signup - digest - resource |
| PYTHON DEPENDENCIES | |
| PYTHON DEPENDENCIES |
mako |
| SYSTEM DEPENDENCIES | |
| SYSTEM DEPENDENCIES | Not have |
| DESCRIPTION | |
| DESCRIPTION | This module has all the mechanics to support product configuration. It serves as a base dependency for configuration interfaces. |
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
config_step_form_view |
product.configurator.config.step.form | product.config.step | form | New |
config_step_tree_view |
product.configurator.config.step.tree | product.config.step | form | New |
configurator_settings_view_form |
res.config.settings.view.form.inherit.sale | res.config.settings | xpath | Inherits base.res_config_settings_view_form |
product_attribute_form_view |
product.attribute.form.view | product.attribute | xpath | Inherits product.product_attribute_view_form |
product_attribute_tree_view |
product.config.product.attribute.tree | product.attribute | xpath | Inherits product.attribute_tree_view |
product_attribute_value_form_view |
product.config.product.attribute.value.form.view | product.attribute.value | form | New |
product_attribute_value_list |
product.attribute.value.list.inherit | product.attribute.value | xpath | Inherits product.product_attribute_value_list |
product_config_domain_form_view |
product.configurator.domain.form | product.config.domain | form | New |
product_config_domain_form_view_template |
product.configurator.domain.form.template | product.config.domain | form | New |
product_config_session_form_view |
product.config.session.form | product.config.session | form | New |
product_config_session_tree_view |
product.config.session.tree | product.config.session | tree | New |
product_configurator_form |
product.configurator | product.configurator | form | New |
product_form_view_custom_vals_inherit |
product.configurator.form.view.custom.vals | product.product | xpath | Inherits product.product_normal_form_view |
product_kanban_view_inherited |
Product Kanban | product.product | xpath | Inherits product.product_kanban_view |
product_template_attribute_line_form_config |
product.template.attribute.line.form | product.template.attribute.line | xpath | Inherits product.product_template_attribute_line_form |
product_template_attribute_value_view_form_weight_extra |
product.template.attribute.value.view.form.weight.extra | product.template.attribute.value | xpath | Inherits product.product_template_attribute_value_view_form |
product_template_attribute_value_view_tree_weight_extra |
product.template.attribute.value.view.tree.weight.extra | product.template.attribute.value | xpath | Inherits product.product_template_attribute_value_view_tree |
product_template_form_view_config_inherited |
product.template.common.form | product.template | xpath | Inherits product.product_template_form_view |
product_template_kanban_view_inherited |
Product.template.product.kanban | product.template | xpath | Inherits product.product_template_kanban_view |
product_template_only_form_view_inherited |
product.configurator.product.template.form | product.template | xpath | Inherits product.product_template_only_form_view |
product_template_search_view |
product.configurator.product.template.search.view | product.template | xpath | Inherits product.product_template_search_view |
product_variant_easy_edit_view_inherit |
product.product.view.form.easy | product.product | xpath | Inherits product.product_variant_easy_edit_view |
template_view_tree_configurable |
product.template.product.tree | product.template | xpath | Inherits product.product_template_tree_view |
No new fields.
Public methods (0)No public methods.
active
Boolean
default=True
help='By unchecking the active field you can disable a attribute without deleting it'
custom_type
Selection
help='The type of the custom field generated in the frontend'
selection=CUSTOM_TYPES
string='Field Type'
description
Text
translate=True
image
Binary
max_val
Integer
help='Maximum value allowed'
string='Max Value'
min_val
Integer
help='Minimum value allowed'
string='Min Value'
multi
Boolean
help='Allow selection of multiple values for this attribute?'
required
Boolean
default=True
help='Determines the required value of this attribute though it can be change on the template level'
search_ok
Boolean
help='When checking for variants with the same configuration, do we include this field in the search?'
string='Searchable'
uom_id
Many2one → uom.uom
comodel_name='uom.uom'
string='Unit of Measure'
val_custom
Boolean
help='Allow custom value for this attribute?'
string='Custom Value'
check_searchable_field(self)
copy(self, default=None)
onchange_custom_type(self)
onchange_val_custom_field(self)
validate_custom_val(self, val)
active
Boolean
default=True
help='By unchecking the active field you can disable a attribute value without deleting it'
image
Binary
attachment=True
help='Attribute value image (Display on website for radio buttons)'
product_id
Many2one → product.product
comodel_name='product.product'
copy(self, default=None)
get_attribute_value_extra_prices(self, product_tmpl_id, pt_attr_value_ids, pricelist=None)
name_search(self, name='', args=None, operator='ilike', limit=100)
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
related='value_id.attribute_id'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
product_value_ids
Many2many → product.attribute.value
column1='product_val_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
compute='_compute_get_value_id'
relation='product_attr_values_attr_values_rel'
store=True
sequence
Integer
default=10
value_id
Many2one → product.attribute.value
comodel_name='product.attribute.value'
required=True
string='Attribute Value'
value_ids
Many2many → product.attribute.value
column1='product_attribute_value_line_id'
column2='product_attribute_value_id'
comodel_name='product.attribute.value'
relation='product_attribute_value_product_attribute_value_line_rel'
string='Values Configuration'
No public methods.
domain_line_ids
One2many → product.config.domain.line
comodel_name='product.config.domain.line'
copy=True
inverse_name='domain_id'
required=True
string='Restrictions'
implied_ids
Many2many → product.config.domain
column1='domain_id'
column2='parent_id'
comodel_name='product.config.domain'
relation='product_config_domain_implied_rel'
string='Inherited'
name
Char
required=True
trans_implied_ids
Many2many → product.config.domain
column1='domain_id'
column2='parent_id'
comodel_name='product.config.domain'
compute=_get_trans_implied
string='Transitively inherits'
compute_domain(self)
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
domain=<expr>
required=True
string='Attribute'
condition
Selection
required=True
selection=_get_domain_conditions
domain_id
Many2one → product.config.domain
comodel_name='product.config.domain'
required=True
string='Rule'
operator
Selection
default='and'
required=True
selection=_get_domain_operators
string='Operators'
sequence
Integer
default=1
help='Set the order of operations for evaluation domain lines'
template_attribute_value_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_template_attribute_value_ids'
string='Template Attribute Values'
value_ids
Many2many → product.attribute.value
column1='line_id'
column2='attribute_id'
comodel_name='product.attribute.value'
relation='product_config_domain_line_attr_rel'
required=True
string='Values'
No public methods.
name
Char
required=True
translate=True
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product'
sequence
Integer
default=10
value_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
string='Configuration'
No public methods.
attr_line_val_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_attr_line_val_ids'
help="For normal attributes the values configured for the product can be selected.\nFor custom attributes the 'Custom' value can also be selected."
string='Allowed Attribute Values'
attribute_line_id
Many2one → product.template.attribute.line
comodel_name='product.template.attribute.line'
ondelete='cascade'
required=True
string='Attribute Line'
domain_id
Many2one → product.config.domain
comodel_name='product.config.domain'
required=True
string='Restrictions'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
sequence
Integer
default=10
template_attribute_ids
Many2many → product.attribute
comodel_name='product.attribute'
compute='_compute_template_attribute_ids'
string='Template Attributes'
value_ids
Many2many → product.attribute.value
column1='cfg_line_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
relation='cfg_line_attr_val_id_rel'
string='Values'
check_value_attributes(self)
onchange_attribute(self)
config_step
Char
string='Configuration Step ID'
config_step_name
Char
compute='_compute_config_step_name'
string='Configuration Step'
currency_id
Many2one → res.currency
comodel_name='res.currency'
compute='_compute_currency_id'
string='Currency'
custom_value_ids
One2many → product.config.session.custom.value
comodel_name='product.config.session.custom.value'
inverse_name='cfg_session_id'
string='Custom Values'
name
Char
readonly=True
string='Configuration Session Number'
price
Float
compute='_compute_cfg_price'
digits='Product Price'
store=True
product_id
Many2one → product.product
comodel_name='product.product'
name='Configured Variant'
ondelete='cascade'
product_preset_id
Many2one → product.product
comodel_name='product.product'
domain="[('product_tmpl_id', '=', product_tmpl_id), ('config_preset_ok', '=', True)]"
string='Preset'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
domain=[('config_ok', '=', True)]
required=True
string='Configurable Template'
state
Selection
default='draft'
required=True
selection=[('draft', 'Draft'), ('done', 'Done')]
user_id
Many2one → res.users
comodel_name='res.users'
required=True
string='User'
value_ids
Many2many → product.attribute.value
column1='cfg_session_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
relation='product_config_session_attr_values_rel'
weight
Float
compute='_compute_cfg_weight'
digits='Stock Weight'
action_confirm(self, product_id=None)
check_and_open_incomplete_step(self, value_ids=None, custom_value_ids=None)
check_attributes_configuration(self, attribute_line_ids, custom_vals, value_ids, final=True)
create(self, vals_list)
create_get_session(self, product_tmpl_id, parent_id=None, force_create=False, user_id=None)
create_get_variant(self, value_ids=None, custom_vals=None)
encode_custom_values(self, custom_vals)
flatten_val_ids(self, value_ids)
formatPrices(self, prices=None, dp='Product Price')
get_active_step(self)
get_adjacent_steps(self, value_ids=None, active_step_line_id=None)
get_all_step_lines(self, product_tmpl_id=None)
get_cfg_price(self, value_ids=None, custom_vals=None)
get_cfg_weight(self, value_ids=None, custom_vals=None)
get_child_specification(self, model, parent)
get_components_prices(self, prices, pricelist, value_ids=None)
get_config_image(self, value_ids=None, custom_vals=None, size=None)
get_custom_value_id(self)
get_extra_attribute_line_ids(self, product_template_id)
get_next_step(self, state, product_tmpl_id=False, value_ids=False, custom_value_ids=False)
get_onchange_specifications(self, model)
get_open_step_lines(self, value_ids=None)
get_session_search_domain(self, product_tmpl_id, state='draft', parent_id=None)
get_session_vals(self, product_tmpl_id, parent_id=None, user_id=None)
get_vals_to_write(self, values, model)
get_variant_search_domain(self, product_tmpl_id, value_ids=None)
get_variant_vals(self, value_ids=None, custom_vals=None, **kwargs)
search_session(self, product_tmpl_id, parent_id=None)
search_variant(self, value_ids=None, product_tmpl_id=None)
update_config(self, attr_val_dict=None, custom_val_dict=None)
update_session_configuration_value(self, vals, product_tmpl_id=None)
validate_configuration(self, value_ids=None, custom_vals=None, product_tmpl_id=False, final=True)
validate_domains_against_sels(self, domains, value_ids=None, custom_vals=None)
values_available(self, check_val_ids=None, value_ids=None, custom_vals=None, product_tmpl_id=None, product_template_attribute_line_id=None)
write(self, vals)
attachment_ids
Many2many → ir.attachment
column1='cfg_sesion_custom_val_id'
column2='attachment_id'
comodel_name='ir.attachment'
relation='product_config_session_custom_value_attachment_rel'
string='Attachments'
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
required=True
string='Attribute'
cfg_session_id
Many2one → product.config.session
comodel_name='product.config.session'
ondelete='cascade'
required=True
string='Session'
name
Char
compute='_compute_val_name'
readonly=True
store=True
value
Char
help='Custom value held as string'
check_custom_type(self)
eval(self)
unique_attribute(self)
name
Char
required=True
translate=True
No public methods.
attribute_line_ids
Many2many → product.template.attribute.line
column1='cfg_line_id'
column2='attr_id'
comodel_name='product.template.attribute.line'
relation='config_step_line_attr_id_rel'
string='Attribute Lines'
config_step_id
Many2one → product.config.step
comodel_name='product.config.step'
required=True
string='Configuration Step'
name
Char
related='config_step_id.name'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
sequence
Integer
default=10
No public methods.
attribute_line_ids
One2many → product.template.attribute.line
comodel_name='product.template.attribute.line'
compute='_compute_attr_lines'
readonly=True
store=False
string='Attributes'
config_session_id
Many2one → product.config.session
comodel_name='product.config.session'
ondelete='cascade'
required=True
string='Configuration Session'
config_step_ids
Many2many → product.config.step
column1='config_wiz_id'
column2='config_step_id'
comodel_name='product.config.step'
readonly=True
relation='product_config_config_steps_rel'
store=False
string='Configuration Steps'
product_id
Many2one → product.product
comodel_name='product.product'
help='Set only when re-configuring a existing variant'
readonly=True
string='Product Variant'
product_img
Binary
compute='_compute_cfg_image'
readonly=True
action_config_done(self)
action_next_step(self)
action_previous_step(self)
action_reset(self)
add_dynamic_fields(self, res, dynamic_fields, wiz)
apply_onchange_values(self, values, field_names, field_onchange)
create(self, vals_list)
fields_get(self, allfields=None, write_access=True, attributes=None)
get_field_default_attrs(self)
get_form_vals(self, dynamic_fields, domains, cfg_val_ids=None, product_tmpl_id=None, config_session_id=None, values=None)
get_onchange_domains(self, cfg_val_ids, product_tmpl_id=False, config_session_id=False)
get_onchange_vals(self, cfg_val_ids, config_session_id=None)
get_state_selection(self)
get_view(self, view_id=None, view_type='form', **options)
get_wizard_action(self, view_cache=False, wizard=None)
onchange(self, values: dict, field_names: <expr>, fields_spec: dict)
onchange_product_tmpl(self)
open_step(self, step)
prepare_attrs_initial(self, attr_lines, field_prefix, custom_field_prefix, dynamic_fields, wiz)
read(self, fields=None, load='_classic_read')
write(self, vals)
config_name
Char
compute='_compute_config_name'
string='Configuration Name'
config_preset_ok
Boolean
string='Is Preset'
weight
Float
compute='_compute_product_weight'
inverse='_inverse_product_weight'
search='_search_product_weight'
store=False
weight_dummy
Float
digits='Stock Weight'
string='Manual Weight'
weight_extra
Float
compute='_compute_product_weight_extra'
check_config_user_access(self, mode)
create(self, vals_list)
reconfigure_product(self)
unlink(self)
write(self, vals)
attribute_line_val_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_template_attr_vals'
store=False
attribute_value_line_ids
One2many → product.attribute.value.line
comodel_name='product.attribute.value.line'
copy=True
inverse_name='product_tmpl_id'
string='Attribute Value Lines'
config_image_ids
One2many → product.config.image
comodel_name='product.config.image'
copy=True
inverse_name='product_tmpl_id'
string='Configuration Images'
config_line_ids
One2many → product.config.line
comodel_name='product.config.line'
copy=False
inverse_name='product_tmpl_id'
string='Attribute Dependencies'
config_ok
Boolean
string='Can be Configured'
config_step_line_ids
One2many → product.config.step.line
comodel_name='product.config.step.line'
copy=False
inverse_name='product_tmpl_id'
string='Configuration Lines'
mako_tmpl_name
Text
copy=True
help='Generate Name based on Mako Template'
string='Variant name'
weight
Float
compute='_compute_weight'
inverse='_set_weight'
search='_search_weight'
store=False
weight_dummy
Float
digits='Stock Weight'
help='Manual setting of product template weight'
string='Manual Weight'
check_attr_value_ids(self)
check_config_user_access(self)
configure_product(self)
copy(self, default=None)
create(self, vals_list)
create_config_wizard(self, model_name='product.configurator', extra_vals=None, click_next=True)
toggle_config(self)
unlink(self)
write(self, vals)
custom
Boolean
help='Allow custom values for this attribute?'
default_val
Many2one → product.attribute.value
comodel_name='product.attribute.value'
multi
Boolean
help='Allow selection of multiple values for this attribute?'
required
Boolean
help='Is this attribute required?'
sequence
Integer
default=10
onchange_attribute(self)
onchange_values(self)
weight_extra
Float
digits='Stock Weight'
string='Attribute Weight Extra'
No public methods.
| REPOSITORY | |
|---|---|
| REPOSITORY | OCA/product-configurator |
| GIT | |
| GIT | https://github.com/OCA/product-configurator.git |
| GIT FOLDER | |
| GIT FOLDER | https://github.com/OCA/product-configurator/tree/16.0/product_configurator |
| VERSION | |
| VERSION | 1.1.2 |
| CATEGORY | |
| CATEGORY | Generic Modules/Base |
| LICENSE | |
| LICENSE | AGPL-3 |
| APPLICATION | |
| APPLICATION | Yes |
| AUTO-INSTALLABLE | |
| AUTO-INSTALLABLE | No |
| AUTHORS | |
| AUTHORS | Odoo Community Association (OCA), Pledra |
| MAINTAINERS | |
| MAINTAINERS | Odoo Community Association (OCA), Pledra |
| COMMITTERS | |
| COMMITTERS | Daniel Reis, Weblate, OCA-git-bot, Simone Rubino, Simone Orsi, oca-ci |
| WEBSITE | |
| WEBSITE | https://github.com/OCA/product-configurator |
| LAST TRACKING UPDATE | |
| LAST TRACKING UPDATE | 2026-07-06 00:53:41 |
| ODOO DEPENDENCIES | |
| ODOO DEPENDENCIES |
odoo/odoo: - account - base_setup - base - web - product - bus - web_tour - uom - analytic - portal - web_editor - http_routing - auth_signup - digest - resource |
| PYTHON DEPENDENCIES | |
| PYTHON DEPENDENCIES |
mako |
| SYSTEM DEPENDENCIES | |
| SYSTEM DEPENDENCIES | Not have |
| DESCRIPTION | |
| DESCRIPTION | |
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
config_step_form_view |
product.configurator.config.step.form | product.config.step | form | New |
config_step_tree_view |
product.configurator.config.step.tree | product.config.step | form | New |
configurator_settings_view_form |
res.config.settings.view.form.inherit.sale | res.config.settings | xpath | Inherits base.res_config_settings_view_form |
product_attribute_form_view |
product.attribute.form.view | product.attribute | xpath | Inherits product.product_attribute_view_form |
product_attribute_tree_view |
product.config.product.attribute.tree | product.attribute | xpath | Inherits product.attribute_tree_view |
product_attribute_value_form_view |
product.config.product.attribute.value.form.view | product.attribute.value | form | New |
product_config_domain_form_view |
product.configurator.domain.form | product.config.domain | form | New |
product_config_domain_form_view_template |
product.configurator.domain.form.template | product.config.domain | form | New |
product_config_session_form_view |
product.config.session.form | product.config.session | form | New |
product_config_session_tree_view |
product.config.session.tree | product.config.session | tree | New |
product_configurator_form |
product.configurator | product.configurator | form | New |
product_form_view_custom_vals_inherit |
product.configurator.form.view.custom.vals | product.product | xpath | Inherits product.product_normal_form_view |
product_kanban_view_inherited |
Product Kanban | product.product | xpath | Inherits product.product_kanban_view |
product_template_attribute_line_form_config |
product.template.attribute.line.form | product.template.attribute.line | xpath | Inherits product.product_template_attribute_line_form |
product_template_attribute_value_view_form_weight_extra |
product.template.attribute.value.view.form.weight.extra | product.template.attribute.value | xpath | Inherits product.product_template_attribute_value_view_form |
product_template_attribute_value_view_tree_weight_extra |
product.template.attribute.value.view.tree.weight.extra | product.template.attribute.value | xpath | Inherits product.product_template_attribute_value_view_tree |
product_template_form_view_config_inherited |
product.template.common.form | product.template | xpath | Inherits product.product_template_form_view |
product_template_kanban_view_inherited |
Product.template.product.kanban | product.template | xpath | Inherits product.product_template_kanban_view |
product_template_only_form_view_inherited |
product.configurator.product.template.form | product.template | xpath | Inherits product.product_template_only_form_view |
product_template_search_view |
product.configurator.product.template.search.view | product.template | xpath | Inherits product.product_template_search_view |
product_variant_easy_edit_view_inherit |
product.product.view.form.easy | product.product | xpath | Inherits product.product_variant_easy_edit_view |
template_view_tree_configurable |
product.template.product.tree | product.template | xpath | Inherits product.product_template_tree_view |
variants_tree_view |
product.attribute.value.tree | product.attribute.value | tree | New |
No new fields.
Public methods (0)No public methods.
active
Boolean
default=True
help='By unchecking the active field you can disable a attribute without deleting it'
custom_type
Selection
help='The type of the custom field generated in the frontend'
selection=CUSTOM_TYPES
string='Field Type'
description
Text
translate=True
image
Binary
max_val
Integer
help='Maximum value allowed'
string='Max Value'
min_val
Integer
help='Minimum value allowed'
string='Min Value'
multi
Boolean
help='Allow selection of multiple values for this attribute?'
required
Boolean
default=True
help='Determines the required value of this attribute though it can be change on the template level'
search_ok
Boolean
help='When checking for variants with the same configuration, do we include this field in the search?'
string='Searchable'
uom_id
Many2one → uom.uom
comodel_name='uom.uom'
string='Unit of Measure'
val_custom
Boolean
help='Allow custom value for this attribute?'
string='Custom Value'
check_searchable_field(self)
copy(self, default=None)
onchange_custom_type(self)
onchange_val_custom_field(self)
validate_custom_val(self, val)
active
Boolean
default=True
help='By unchecking the active field you can disable a attribute value without deleting it'
image
Binary
attachment=True
help='Attribute value image (Display on website for radio buttons)'
product_id
Many2one → product.product
comodel_name='product.product'
copy(self, default=None)
get_attribute_value_extra_prices(self, product_tmpl_id, pt_attr_value_ids, pricelist=None)
name_get(self)
name_search(self, name='', args=None, operator='ilike', limit=100)
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
related='value_id.attribute_id'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
product_value_ids
Many2many → product.attribute.value
column1='product_val_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
compute='_compute_get_value_id'
relation='product_attr_values_attr_values_rel'
store=True
sequence
Integer
default=10
value_id
Many2one → product.attribute.value
comodel_name='product.attribute.value'
required=True
string='Attribute Value'
value_ids
Many2many → product.attribute.value
column1='product_attribute_value_line_id'
column2='product_attribute_value_id'
comodel_name='product.attribute.value'
relation='product_attribute_value_product_attribute_value_line_rel'
string='Values Configuration'
No public methods.
domain_line_ids
One2many → product.config.domain.line
comodel_name='product.config.domain.line'
copy=True
inverse_name='domain_id'
required=True
string='Restrictions'
implied_ids
Many2many → product.config.domain
column1='domain_id'
column2='parent_id'
comodel_name='product.config.domain'
relation='product_config_domain_implied_rel'
string='Inherited'
name
Char
required=True
trans_implied_ids
Many2many → product.config.domain
column1='domain_id'
column2='parent_id'
comodel_name='product.config.domain'
compute=_get_trans_implied
string='Transitively inherits'
compute_domain(self)
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
domain=<expr>
required=True
string='Attribute'
condition
Selection
required=True
selection=_get_domain_conditions
domain_id
Many2one → product.config.domain
comodel_name='product.config.domain'
required=True
string='Rule'
operator
Selection
default='and'
required=True
selection=_get_domain_operators
string='Operators'
sequence
Integer
default=1
help='Set the order of operations for evaluation domain lines'
template_attribute_value_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_template_attribute_value_ids'
string='Template Attribute Values'
value_ids
Many2many → product.attribute.value
column1='line_id'
column2='attribute_id'
comodel_name='product.attribute.value'
relation='product_config_domain_line_attr_rel'
required=True
string='Values'
No public methods.
name
Char
required=True
translate=True
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product'
sequence
Integer
default=10
value_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
string='Configuration'
No public methods.
attr_line_val_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_attr_line_val_ids'
help="For normal attributes the values configured for the product can be selected.\nFor custom attributes the 'Custom' value can also be selected."
string='Allowed Attribute Values'
attribute_line_id
Many2one → product.template.attribute.line
comodel_name='product.template.attribute.line'
ondelete='cascade'
required=True
string='Attribute Line'
domain_id
Many2one → product.config.domain
comodel_name='product.config.domain'
required=True
string='Restrictions'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
sequence
Integer
default=10
template_attribute_ids
Many2many → product.attribute
comodel_name='product.attribute'
compute='_compute_template_attribute_ids'
string='Template Attributes'
value_ids
Many2many → product.attribute.value
column1='cfg_line_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
relation='cfg_line_attr_val_id_rel'
string='Values'
check_value_attributes(self)
onchange_attribute(self)
config_step
Char
string='Configuration Step ID'
config_step_name
Char
compute='_compute_config_step_name'
string='Configuration Step'
currency_id
Many2one → res.currency
comodel_name='res.currency'
compute='_compute_currency_id'
string='Currency'
custom_value_ids
One2many → product.config.session.custom.value
comodel_name='product.config.session.custom.value'
inverse_name='cfg_session_id'
string='Custom Values'
name
Char
readonly=True
string='Configuration Session Number'
price
Float
compute='_compute_cfg_price'
digits='Product Price'
store=True
product_id
Many2one → product.product
comodel_name='product.product'
name='Configured Variant'
ondelete='cascade'
product_preset_id
Many2one → product.product
comodel_name='product.product'
domain="[('product_tmpl_id', '=', product_tmpl_id), ('config_preset_ok', '=', True)]"
string='Preset'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
domain=[('config_ok', '=', True)]
required=True
string='Configurable Template'
state
Selection
default='draft'
required=True
selection=[('draft', 'Draft'), ('done', 'Done')]
user_id
Many2one → res.users
comodel_name='res.users'
required=True
string='User'
value_ids
Many2many → product.attribute.value
column1='cfg_session_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
relation='product_config_session_attr_values_rel'
weight
Float
compute='_compute_cfg_weight'
digits='Stock Weight'
action_confirm(self, product_id=None)
check_and_open_incomplete_step(self, value_ids=None, custom_value_ids=None)
check_attributes_configuration(self, attribute_line_ids, custom_vals, value_ids, final=True)
create(self, vals_list)
create_get_session(self, product_tmpl_id, parent_id=None, force_create=False, user_id=None)
create_get_variant(self, value_ids=None, custom_vals=None)
encode_custom_values(self, custom_vals)
flatten_val_ids(self, value_ids)
formatPrices(self, prices=None, dp='Product Price')
get_active_step(self)
get_adjacent_steps(self, value_ids=None, active_step_line_id=None)
get_all_step_lines(self, product_tmpl_id=None)
get_cfg_price(self, value_ids=None, custom_vals=None)
get_cfg_weight(self, value_ids=None, custom_vals=None)
get_child_specification(self, model, parent)
get_components_prices(self, prices, pricelist, value_ids=None)
get_config_image(self, value_ids=None, custom_vals=None, size=None)
get_custom_value_id(self)
get_extra_attribute_line_ids(self, product_template_id)
get_next_step(self, state, product_tmpl_id=False, value_ids=False, custom_value_ids=False)
get_onchange_specifications(self, model)
get_open_step_lines(self, value_ids=None)
get_session_search_domain(self, product_tmpl_id, state='draft', parent_id=None)
get_session_vals(self, product_tmpl_id, parent_id=None, user_id=None)
get_vals_to_write(self, values, model)
get_variant_search_domain(self, product_tmpl_id, value_ids=None)
get_variant_vals(self, value_ids=None, custom_vals=None, **kwargs)
search_session(self, product_tmpl_id, parent_id=None)
search_variant(self, value_ids=None, product_tmpl_id=None)
update_config(self, attr_val_dict=None, custom_val_dict=None)
update_session_configuration_value(self, vals, product_tmpl_id=None)
validate_configuration(self, value_ids=None, custom_vals=None, product_tmpl_id=False, final=True)
validate_domains_against_sels(self, domains, value_ids=None, custom_vals=None)
values_available(self, check_val_ids=None, value_ids=None, custom_vals=None, product_tmpl_id=None, product_template_attribute_line_id=None)
write(self, vals)
attachment_ids
Many2many → ir.attachment
column1='cfg_sesion_custom_val_id'
column2='attachment_id'
comodel_name='ir.attachment'
relation='product_config_session_custom_value_attachment_rel'
string='Attachments'
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
required=True
string='Attribute'
cfg_session_id
Many2one → product.config.session
comodel_name='product.config.session'
ondelete='cascade'
required=True
string='Session'
name
Char
compute='_compute_val_name'
readonly=True
store=True
value
Char
help='Custom value held as string'
check_custom_type(self)
eval(self)
unique_attribute(self)
name
Char
required=True
translate=True
No public methods.
attribute_line_ids
Many2many → product.template.attribute.line
column1='cfg_line_id'
column2='attr_id'
comodel_name='product.template.attribute.line'
relation='config_step_line_attr_id_rel'
string='Attribute Lines'
config_step_id
Many2one → product.config.step
comodel_name='product.config.step'
required=True
string='Configuration Step'
name
Char
related='config_step_id.name'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
sequence
Integer
default=10
No public methods.
attribute_line_ids
One2many → product.template.attribute.line
comodel_name='product.template.attribute.line'
compute='_compute_attr_lines'
readonly=True
store=False
string='Attributes'
config_session_id
Many2one → product.config.session
comodel_name='product.config.session'
ondelete='cascade'
required=True
string='Configuration Session'
config_step_ids
Many2many → product.config.step
column1='config_wiz_id'
column2='config_step_id'
comodel_name='product.config.step'
readonly=True
relation='product_config_config_steps_rel'
store=False
string='Configuration Steps'
product_id
Many2one → product.product
comodel_name='product.product'
help='Set only when re-configuring a existing variant'
readonly=True
string='Product Variant'
product_img
Binary
compute='_compute_cfg_image'
readonly=True
action_config_done(self)
action_next_step(self)
action_previous_step(self)
action_reset(self)
add_dynamic_fields(self, res, dynamic_fields, wiz)
apply_onchange_values(self, values, field_name, field_onchange)
create(self, vals_list)
fields_get(self, allfields=None, write_access=True, attributes=None)
get_field_default_attrs(self)
get_form_vals(self, dynamic_fields, domains, cfg_val_ids=None, product_tmpl_id=None, config_session_id=None)
get_onchange_domains(self, values, cfg_val_ids, product_tmpl_id=False, config_session_id=False)
get_onchange_vals(self, cfg_val_ids, config_session_id=None)
get_state_selection(self)
get_view(self, view_id=None, view_type='form', **options)
get_wizard_action(self, view_cache=False, wizard=None)
onchange(self, values, field_name, field_onchange)
onchange_product_tmpl(self)
open_step(self, step)
prepare_attrs_initial(self, attr_lines, field_prefix, custom_field_prefix, dynamic_fields, wiz)
read(self, fields=None, load='_classic_read')
setup_modifiers(self, node, field=None)
write(self, vals)
config_name
Char
compute='_compute_config_name'
string='Configuration Name'
config_preset_ok
Boolean
string='Is Preset'
weight
Float
compute='_compute_product_weight'
inverse='_inverse_product_weight'
search='_search_product_weight'
store=False
weight_dummy
Float
digits='Stock Weight'
string='Manual Weight'
weight_extra
Float
compute='_compute_product_weight_extra'
check_config_user_access(self, mode)
create(self, vals_list)
reconfigure_product(self)
unlink(self)
write(self, vals)
attribute_line_val_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_template_attr_vals'
store=False
attribute_value_line_ids
One2many → product.attribute.value.line
comodel_name='product.attribute.value.line'
copy=True
inverse_name='product_tmpl_id'
string='Attribute Value Lines'
config_image_ids
One2many → product.config.image
comodel_name='product.config.image'
copy=True
inverse_name='product_tmpl_id'
string='Configuration Images'
config_line_ids
One2many → product.config.line
comodel_name='product.config.line'
copy=False
inverse_name='product_tmpl_id'
string='Attribute Dependencies'
config_ok
Boolean
string='Can be Configured'
config_step_line_ids
One2many → product.config.step.line
comodel_name='product.config.step.line'
copy=False
inverse_name='product_tmpl_id'
string='Configuration Lines'
mako_tmpl_name
Text
copy=True
help='Generate Name based on Mako Template'
string='Variant name'
weight
Float
compute='_compute_weight'
inverse='_set_weight'
search='_search_weight'
store=False
weight_dummy
Float
digits='Stock Weight'
help='Manual setting of product template weight'
string='Manual Weight'
check_attr_value_ids(self)
check_config_user_access(self)
configure_product(self)
copy(self, default=None)
create(self, vals_list)
create_config_wizard(self, model_name='product.configurator', extra_vals=None, click_next=True)
toggle_config(self)
unlink(self)
write(self, vals)
custom
Boolean
help='Allow custom values for this attribute?'
default_val
Many2one → product.attribute.value
comodel_name='product.attribute.value'
multi
Boolean
help='Allow selection of multiple values for this attribute?'
required
Boolean
help='Is this attribute required?'
sequence
Integer
default=10
onchange_attribute(self)
onchange_values(self)
weight_extra
Float
digits='Stock Weight'
string='Attribute Weight Extra'
No public methods.
| REPOSITORY | |
|---|---|
| REPOSITORY | OCA/product-configurator |
| GIT | |
| GIT | https://github.com/OCA/product-configurator.git |
| GIT FOLDER | |
| GIT FOLDER | https://github.com/OCA/product-configurator/tree/14.0/product_configurator |
| VERSION | |
| VERSION | 1.4.0 |
| CATEGORY | |
| CATEGORY | Generic Modules/Base |
| LICENSE | |
| LICENSE | AGPL-3 |
| APPLICATION | |
| APPLICATION | Yes |
| AUTO-INSTALLABLE | |
| AUTO-INSTALLABLE | No |
| AUTHORS | |
| AUTHORS | Odoo Community Association (OCA), Pledra |
| MAINTAINERS | |
| MAINTAINERS | Odoo Community Association (OCA), Pledra |
| COMMITTERS | |
| COMMITTERS | Paul Catinean, Daniel Reis, Donatas, oca-travis, Weblate, OCA-git-bot, Benjamin Henquet, Chandresh Thakkar, Patrick Wilson, Chandresh Thakkar OSI, SHS, RUS, csil300, HET, Julio c Bravo, RabbitJon-S73 |
| WEBSITE | |
| WEBSITE | https://github.com/OCA/product-configurator |
| LAST TRACKING UPDATE | |
| LAST TRACKING UPDATE | 2026-07-06 00:40:50 |
| ODOO DEPENDENCIES | |
| ODOO DEPENDENCIES |
odoo/odoo: - account - base_setup - base - web - product - bus - web_tour - uom - analytic - portal - web_editor - http_routing - auth_signup - digest - resource |
| PYTHON DEPENDENCIES | |
| PYTHON DEPENDENCIES | Not have |
| SYSTEM DEPENDENCIES | |
| SYSTEM DEPENDENCIES | Not have |
| DESCRIPTION | |
| DESCRIPTION | |
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
assets_backend |
Product Configurator Assets | ir.ui.view | qweb | Inherits web.assets_backend |
config_step_form_view |
product.configurator.config.step.form | product.config.step | form | New |
config_step_tree_view |
product.configurator.config.step.tree | product.config.step | form | New |
configurator_settings_view_form |
res.config.settings.view.form.inherit.sale | res.config.settings | xpath | Inherits base.res_config_settings_view_form |
product_attribute_form_view |
product.attribute.form.view | product.attribute | xpath | Inherits product.product_attribute_view_form |
product_attribute_tree_view |
product.config.product.attribute.tree | product.attribute | xpath | Inherits product.attribute_tree_view |
product_attribute_value_form_view |
product.config.product.attribute.value.form.view | product.attribute.value | form | New |
product_config_domain_form_view |
product.configurator.domain.form | product.config.domain | form | New |
product_config_domain_form_view_template |
product.configurator.domain.form.template | product.config.domain | form | New |
product_config_session_form_view |
product.config.session.form | product.config.session | form | New |
product_config_session_tree_view |
product.config.session.tree | product.config.session | tree | New |
product_configurator_form |
product.configurator | product.configurator | form | New |
product_form_view_custom_vals_inherit |
product.configurator.form.view.custom.vals | product.product | xpath | Inherits product.product_normal_form_view |
product_kanban_view_inherited |
Product Kanban | product.product | xpath | Inherits product.product_kanban_view |
product_template_attribute_line_form_config |
product.template.attribute.line.form | product.template.attribute.line | xpath | Inherits product.product_template_attribute_line_form |
product_template_attribute_value_view_form_weight_extra |
product.template.attribute.value.view.form.weight.extra | product.template.attribute.value | xpath | Inherits product.product_template_attribute_value_view_form |
product_template_attribute_value_view_tree_weight_extra |
product.template.attribute.value.view.tree.weight.extra | product.template.attribute.value | xpath | Inherits product.product_template_attribute_value_view_tree |
product_template_form_view_config_inherited |
product.template.common.form | product.template | xpath | Inherits product.product_template_form_view |
product_template_kanban_view_inherited |
Product.template.product.kanban | product.template | xpath | Inherits product.product_template_kanban_view |
product_template_only_form_view_inherited |
product.configurator.product.template.form | product.template | xpath | Inherits product.product_template_only_form_view |
product_template_search_view |
product.configurator.product.template.search.view | product.template | xpath | Inherits product.product_template_search_view |
product_variant_easy_edit_view_inherit |
product.product.view.form.easy | product.product | xpath | Inherits product.product_variant_easy_edit_view |
template_view_tree_configurable |
product.template.product.tree | product.template | xpath | Inherits product.product_template_tree_view |
variants_tree_view |
product.attribute.value.tree | product.attribute.value | tree | New |
No new fields.
Public methods (0)No public methods.
active
Boolean
default=True
help='By unchecking the active field you can disable a attribute without deleting it'
string='Active'
custom_type
Selection
help='The type of the custom field generated in the frontend'
selection=CUSTOM_TYPES
string='Field Type'
description
Text
string='Description'
translate=True
image
Binary
string='Image'
max_val
Integer
help='Maximum value allowed'
string='Max Value'
min_val
Integer
help='Minimum value allowed'
string='Min Value'
multi
Boolean
help='Allow selection of multiple values for this attribute?'
string='Multi'
required
Boolean
default=True
help='Determines the required value of this attribute though it can be change on the template level'
string='Required'
search_ok
Boolean
help='When checking for variants with the same configuration, do we include this field in the search?'
string='Searchable'
uom_id
Many2one → uom.uom
comodel_name='uom.uom'
string='Unit of Measure'
val_custom
Boolean
help='Allow custom value for this attribute?'
string='Custom Value'
check_searchable_field(self)
copy(self, default=None)
onchange_custom_type(self)
onchange_val_custom_field(self)
validate_custom_val(self, val)
active
Boolean
default=True
help='By unchecking the active field you can disable a attribute value without deleting it'
string='Active'
image
Binary
attachment=True
help='Attribute value image (Display on website for radio buttons)'
string='Image'
product_id
Many2one → product.product
comodel_name='product.product'
string='Related Product'
copy(self, default=None)
get_attribute_value_extra_prices(self, product_tmpl_id, pt_attr_value_ids, pricelist=None)
name_get(self)
name_search(self, name='', args=None, operator='ilike', limit=100)
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
related='value_id.attribute_id'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
product_value_ids
Many2many → product.attribute.value
column1='product_val_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
compute='_compute_get_value_id'
relation='product_attr_values_attr_values_rel'
store=True
sequence
Integer
default=10
string='Sequence'
value_id
Many2one → product.attribute.value
comodel_name='product.attribute.value'
required='True'
string='Attribute Value'
value_ids
Many2many → product.attribute.value
column1='product_attribute_value_line_id'
column2='product_attribute_value_id'
comodel_name='product.attribute.value'
relation='product_attribute_value_product_attribute_value_line_rel'
string='Values Configuration'
No public methods.
domain_line_ids
One2many → product.config.domain.line
comodel_name='product.config.domain.line'
copy=True
inverse_name='domain_id'
required=True
string='Restrictions'
implied_ids
Many2many → product.config.domain
column1='domain_id'
column2='parent_id'
comodel_name='product.config.domain'
relation='product_config_domain_implied_rel'
string='Inherited'
name
Char
required=True
string='Name'
trans_implied_ids
Many2many → product.config.domain
column1='domain_id'
column2='parent_id'
comodel_name='product.config.domain'
compute=_get_trans_implied
string='Transitively inherits'
compute_domain(self)
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
required=True
string='Attribute'
condition
Selection
required=True
selection=_get_domain_conditions
string='Condition'
domain_id
Many2one → product.config.domain
comodel_name='product.config.domain'
required=True
string='Rule'
operator
Selection
default='and'
required=True
selection=_get_domain_operators
string='Operators'
sequence
Integer
default=1
help='Set the order of operations for evaluation domain lines'
string='Sequence'
template_attribute_value_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_template_attribute_value_ids'
string='Template Attribute Values'
value_ids
Many2many → product.attribute.value
column1='line_id'
column2='attribute_id'
comodel_name='product.attribute.value'
relation='product_config_domain_line_attr_rel'
required=True
string='Values'
No public methods.
name
Char
required=True
translate=True
args: 'Name'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product'
sequence
Integer
default=10
string='Sequence'
value_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
string='Configuration'
No public methods.
attr_line_val_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
related='attribute_line_id.value_ids'
string='Attribute Line Values'
attribute_line_id
Many2one → product.template.attribute.line
comodel_name='product.template.attribute.line'
ondelete='cascade'
required=True
string='Attribute Line'
domain_id
Many2one → product.config.domain
comodel_name='product.config.domain'
required=True
string='Restrictions'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
sequence
Integer
default=10
string='Sequence'
template_attribute_ids
Many2many → product.attribute
comodel_name='product.attribute'
compute='_compute_template_attribute_ids'
string='Template Attributes'
value_ids
Many2many → product.attribute.value
column1='cfg_line_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
relation='cfg_line_attr_val_id_rel'
string='Values'
check_value_attributes(self)
onchange_attribute(self)
config_step
Char
string='Configuration Step ID'
config_step_name
Char
compute='_compute_config_step_name'
string='Configuration Step'
currency_id
Many2one → res.currency
comodel_name='res.currency'
compute='_compute_currency_id'
string='Currency'
custom_value_ids
One2many → product.config.session.custom.value
comodel_name='product.config.session.custom.value'
inverse_name='cfg_session_id'
string='Custom Values'
name
Char
readonly=True
string='Configuration Session Number'
price
Float
compute='_compute_cfg_price'
digits='Product Price'
store=True
string='Price'
product_id
Many2one → product.product
comodel_name='product.product'
name='Configured Variant'
ondelete='cascade'
product_preset_id
Many2one → product.product
comodel_name='product.product'
domain="[('product_tmpl_id', '=', product_tmpl_id), ('config_preset_ok', '=', True)]"
string='Preset'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
domain=[('config_ok', '=', True)]
required=True
string='Configurable Template'
state
Selection
default='draft'
required=True
selection=[('draft', 'Draft'), ('done', 'Done')]
string='State'
user_id
Many2one → res.users
comodel_name='res.users'
required=True
string='User'
value_ids
Many2many → product.attribute.value
column1='cfg_session_id'
column2='attr_val_id'
comodel_name='product.attribute.value'
relation='product_config_session_attr_values_rel'
weight
Float
compute='_compute_cfg_weight'
digits='Stock Weight'
string='Weight'
action_confirm(self, product_id=None)
check_and_open_incomplete_step(self, value_ids=None, custom_value_ids=None)
check_attributes_configuration(self, attribute_line_ids, custom_vals, value_ids, final=True)
create(self, vals)
create_get_session(self, product_tmpl_id, parent_id=None, force_create=False, user_id=None)
create_get_variant(self, value_ids=None, custom_vals=None)
encode_custom_values(self, custom_vals)
flatten_val_ids(self, value_ids)
formatPrices(self, prices=None, dp='Product Price')
get_active_step(self)
get_adjacent_steps(self, value_ids=None, active_step_line_id=None)
get_all_step_lines(self, product_tmpl_id=None)
get_cfg_price(self, value_ids=None, custom_vals=None)
get_cfg_weight(self, value_ids=None, custom_vals=None)
get_child_specification(self, model, parent)
get_components_prices(self, prices, pricelist, value_ids=None)
get_config_image(self, value_ids=None, custom_vals=None, size=None)
get_custom_value_id(self)
get_extra_attribute_line_ids(self, product_template_id)
get_next_step(self, state, product_tmpl_id=False, value_ids=False, custom_value_ids=False)
get_onchange_specifications(self, model)
get_open_step_lines(self, value_ids=None)
get_session_search_domain(self, product_tmpl_id, state='draft', parent_id=None)
get_session_vals(self, product_tmpl_id, parent_id=None, user_id=None)
get_vals_to_write(self, values, model)
get_variant_search_domain(self, product_tmpl_id, value_ids=None)
get_variant_vals(self, value_ids=None, custom_vals=None, **kwargs)
search_session(self, product_tmpl_id, parent_id=None)
search_variant(self, value_ids=None, product_tmpl_id=None)
update_config(self, attr_val_dict=None, custom_val_dict=None)
update_session_configuration_value(self, vals, product_tmpl_id=None)
validate_configuration(self, value_ids=None, custom_vals=None, product_tmpl_id=False, final=True)
validate_domains_against_sels(self, domains, value_ids=None, custom_vals=None)
values_available(self, check_val_ids=None, value_ids=None, custom_vals=None, product_tmpl_id=None)
write(self, vals)
attachment_ids
Many2many → ir.attachment
column1='cfg_sesion_custom_val_id'
column2='attachment_id'
comodel_name='ir.attachment'
relation='product_config_session_custom_value_attachment_rel'
string='Attachments'
attribute_id
Many2one → product.attribute
comodel_name='product.attribute'
required=True
string='Attribute'
cfg_session_id
Many2one → product.config.session
comodel_name='product.config.session'
ondelete='cascade'
required=True
string='Session'
name
Char
compute='_compute_val_name'
readonly=True
store=True
string='Name'
value
Char
help='Custom value held as string'
string='Value'
check_custom_type(self)
eval(self)
unique_attribute(self)
name
Char
required=True
string='Name'
translate=True
No public methods.
attribute_line_ids
Many2many → product.template.attribute.line
column1='cfg_line_id'
column2='attr_id'
comodel_name='product.template.attribute.line'
relation='config_step_line_attr_id_rel'
string='Attribute Lines'
config_step_id
Many2one → product.config.step
comodel_name='product.config.step'
required=True
string='Configuration Step'
name
Char
related='config_step_id.name'
product_tmpl_id
Many2one → product.template
comodel_name='product.template'
ondelete='cascade'
required=True
string='Product Template'
sequence
Integer
default=10
string='Sequence'
No public methods.
attribute_line_ids
One2many → product.template.attribute.line
comodel_name='product.template.attribute.line'
compute='_compute_attr_lines'
readonly=True
store=False
string='Attributes'
config_session_id
Many2one → product.config.session
comodel_name='product.config.session'
ondelete='cascade'
required=True
string='Configuration Session'
config_step_ids
Many2many → product.config.step
column1='config_wiz_id'
column2='config_step_id'
comodel_name='product.config.step'
readonly=True
relation='product_config_config_steps_rel'
store=False
string='Configuration Steps'
product_id
Many2one → product.product
comodel_name='product.product'
help='Set only when re-configuring a existing variant'
readonly=True
string='Product Variant'
product_img
Binary
compute='_compute_cfg_image'
readonly=True
action_config_done(self)
action_next_step(self)
action_previous_step(self)
action_reset(self)
add_dynamic_fields(self, res, dynamic_fields, wiz)
apply_onchange_values(self, values, field_name, field_onchange)
create(self, vals)
fields_get(self, allfields=None, write_access=True, attributes=None)
fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False)
get_field_default_attrs(self)
get_form_vals(self, dynamic_fields, domains, cfg_val_ids=None, product_tmpl_id=None, config_session_id=None)
get_onchange_domains(self, values, cfg_val_ids, product_tmpl_id=False, config_session_id=False)
get_onchange_vals(self, cfg_val_ids, config_session_id=None)
get_state_selection(self)
get_wizard_action(self, view_cache=False, wizard=None)
onchange(self, values, field_name, field_onchange)
onchange_product_tmpl(self)
open_step(self, step)
prepare_attrs_initial(self, attr_lines, field_prefix, custom_field_prefix, dynamic_fields, wiz)
read(self, fields=None, load='_classic_read')
setup_modifiers(self, node, field=None, context=None, current_node_path=None)
write(self, vals)
config_name
Char
compute='_compute_config_name'
string='Configuration Name'
config_preset_ok
Boolean
string='Is Preset'
weight
Float
compute='_compute_product_weight'
inverse='_inverse_product_weight'
store=True
weight_dummy
Float
digits='Stock Weight'
string='Manual Weight'
weight_extra
Float
compute='_compute_product_weight_extra'
store=True
string='Weight Extra'
check_config_user_access(self, mode)
create(self, vals)
get_product_attribute_values_action(self)
reconfigure_product(self)
unlink(self)
write(self, vals)
attribute_line_val_ids
Many2many → product.attribute.value
comodel_name='product.attribute.value'
compute='_compute_template_attr_vals'
store=False
attribute_value_line_ids
One2many → product.attribute.value.line
comodel_name='product.attribute.value.line'
copy=True
inverse_name='product_tmpl_id'
string='Attribute Value Lines'
config_image_ids
One2many → product.config.image
comodel_name='product.config.image'
copy=True
inverse_name='product_tmpl_id'
string='Configuration Images'
config_line_ids
One2many → product.config.line
comodel_name='product.config.line'
copy=False
inverse_name='product_tmpl_id'
string='Attribute Dependencies'
config_ok
Boolean
string='Can be Configured'
config_step_line_ids
One2many → product.config.step.line
comodel_name='product.config.step.line'
copy=False
inverse_name='product_tmpl_id'
string='Configuration Lines'
mako_tmpl_name
Text
copy=True
help='Generate Name based on Mako Template'
string='Variant name'
weight_dummy
Float
digits='Stock Weight'
help='Manual setting of product template weight'
string='Manual Weight'
check_attr_value_ids(self)
check_config_user_access(self)
configure_product(self)
copy(self, default=None)
create(self, vals)
create_config_wizard(self, model_name='product.configurator', extra_vals=None, click_next=True)
get_product_attribute_values_action(self)
name_search(self, name='', args=None, operator='ilike', limit=100)
toggle_config(self)
unlink(self)
write(self, vals)
custom
Boolean
help='Allow custom values for this attribute?'
string='Custom'
default_val
Many2one → product.attribute.value
comodel_name='product.attribute.value'
string='Default Value'
multi
Boolean
help='Allow selection of multiple values for this attribute?'
string='Multi'
required
Boolean
help='Is this attribute required?'
string='Required'
sequence
Integer
default=10
string='Sequence'
onchange_attribute(self)
onchange_values(self)
weight_extra
Float
digits='Stock Weight'
string='Attribute Weight Extra'
No public methods.
| STATUS | |
|---|---|
| STATUS | Open migration PR - not merged yet for this version |
| REPOSITORY | |
| REPOSITORY | OCA/product-configurator |
| PULL REQUEST | |
| PULL REQUEST | [19.0][MIG] product_configurator: Migration to 19.0. (#168) |