diff --git a/product_configurator/__manifest__.py b/product_configurator/__manifest__.py index 4f75285a..dd241883 100755 --- a/product_configurator/__manifest__.py +++ b/product_configurator/__manifest__.py @@ -24,6 +24,7 @@ 'demo/product_attribute.xml', 'demo/product_config_domain.xml', 'demo/product_config_lines.xml', + 'demo/product_config_defaults.xml', 'demo/product_config_step.xml', 'demo/config_image_ids.xml', ], diff --git a/product_configurator/demo/product_config_defaults.xml b/product_configurator/demo/product_config_defaults.xml new file mode 100644 index 00000000..a305ccc7 --- /dev/null +++ b/product_configurator/demo/product_config_defaults.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/product_configurator/i18n/fr_CA.po b/product_configurator/i18n/fr_CA.po new file mode 100644 index 00000000..f263aa09 --- /dev/null +++ b/product_configurator/i18n/fr_CA.po @@ -0,0 +1,704 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_configurator +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-05-30 20:00+0000\n" +"PO-Revision-Date: 2017-05-30 16:13-0400\n" +"Last-Translator: Stéphane Le Cornec \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"Language: fr_CA\n" +"X-Generator: Poedit 1.8.7\n" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_active +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_value_active +msgid "Active" +msgstr "Actif" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_val_custom +msgid "Allow custom value for this attribute?" +msgstr "Autoriser une valeur personnalisée pour cette caractéristique?" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_line_custom +msgid "Allow custom values for this attribute?" +msgstr "Permettre des valeurs personnalisées pour cette caractéristique?" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_line_multi +#: model:ir.model.fields,help:product_configurator.field_product_attribute_multi +msgid "Allow selection of multiple values for this attribute?" +msgstr "Permettre la sélection de plusieurs valeurs pour cette caractéristique?" + +#. module: product_configurator +#: selection:product.attribute,custom_type:0 +msgid "Attachment" +msgstr "Pièce Jointe" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_value_custom_attachment_ids +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_custom_value_attachment_ids +msgid "Attachments" +msgstr "Pièces jointes" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_value_custom_attribute_id +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_line_attribute_id +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_custom_value_attribute_id +#: model:ir.ui.view,arch_db:product_configurator.product_attribute_value_custom_tree +msgid "Attribute" +msgstr "Caractéristique" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_product_config_line_ids +#: model:ir.model.fields,field_description:product_configurator.field_product_template_config_line_ids +msgid "Attribute Dependencies" +msgstr "Dépendances de la caractéristique" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_line_attribute_line_id +msgid "Attribute Line" +msgstr "Ligne de caractéristique" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_line_attribute_line_ids +msgid "Attribute Lines" +msgstr "Lignes de caractéristique" + +#. module: product_configurator +#: model:ir.ui.view,arch_db:product_configurator.product_template_form_view +msgid "Attribute Value Dependencies" +msgstr "Dépendances de valeur de caractéristique" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_line_attr_line_val_ids +msgid "Attribute Values" +msgstr "Valeurs de caractéristique" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_config.py:510 +#, python-format +msgid "Attribute custom type is binary, attachments are the only accepted values with this custom field type" +msgstr "Caractéristique binaire, les pièces jointes sont les seules valeurs acceptées avec ce type de champ personnalisé" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_config.py:515 +#, python-format +msgid "Attribute custom type must be 'binary' for saving attachments to custom value" +msgstr "La caractéristique doit être binaire pour l’enregistrement des pièces jointes au champ personnalisé" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_value_active +msgid "By unchecking the active field you can disable a attribute value without deleting it" +msgstr "En décochant le champ actif, vous pouvez désactiver une valeur de caractéristique sans le supprimer" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_active +msgid "By unchecking the active field you can disable a attribute without deleting it" +msgstr "En décochant le champ actif, vous pouvez désactiver une caractéristique sans le supprimer" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_product_config_ok +#: model:ir.model.fields,field_description:product_configurator.field_product_template_config_ok +msgid "Can be Configured" +msgstr "Paramétrables." + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_create_on_fly +msgid "Can create value on the fly" +msgstr "Peut créer de la valeur à la volée" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_config.py:269 +#, python-format +msgid "Cannot have a configuration step defined twice." +msgstr "Ne peut pas avoir une étape de configuration défini deux fois." + +#. module: product_configurator +#: sql_constraint:product.attribute.value.custom:0 +msgid "Cannot have two custom values for the same attribute" +msgstr "Ne peut pas avoir deux valeurs personnalisées pour la même caractéristique" + +#. module: product_configurator +#: selection:product.attribute,custom_type:0 +msgid "Char" +msgstr "Char" + +#. module: product_configurator +#: selection:product.attribute,custom_type:0 +msgid "Color" +msgstr "Couleur" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_line_condition +msgid "Condition" +msgstr "Condition" + +#. module: product_configurator +#: model:ir.ui.menu,name:product_configurator.menu_product_configurable +msgid "Configurable Products" +msgstr "Articles configurables" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_product_tmpl_id +msgid "Configurable Template" +msgstr "Modèle configurable" + +#. module: product_configurator +#: model:ir.actions.act_window,name:product_configurator.product_configurable_template_action +#: model:ir.ui.menu,name:product_configurator.menu_product_configurable_template_action +msgid "Configurable Templates" +msgstr "Modèles configurables" + +#. module: product_configurator +#: model:ir.ui.menu,name:product_configurator.menu_product_configurable_variants_action +msgid "Configurable Variants" +msgstr "Variantes configurables" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_image_value_ids +msgid "Configuration" +msgstr "Configuration" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_product_config_image_ids +#: model:ir.model.fields,field_description:product_configurator.field_product_template_config_image_ids +#: model:ir.ui.view,arch_db:product_configurator.product_template_form_view +msgid "Configuration Images" +msgstr "Configuration des Images" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_product_config_step_line_ids +#: model:ir.model.fields,field_description:product_configurator.field_product_template_config_step_line_ids +msgid "Configuration Lines" +msgstr "Lignes de configuration" + +#. module: product_configurator +#: model:ir.ui.view,arch_db:product_configurator.product_template_form_view +msgid "Configuration Options" +msgstr "Options de configuration" + +#. module: product_configurator +#: model:ir.actions.act_window,name:product_configurator.product_config_domain_action +#: model:ir.ui.menu,name:product_configurator.menu_product_config_domain_action +#: model:ir.ui.view,arch_db:product_configurator.product_config_domain_form_view +#: model:ir.ui.view,arch_db:product_configurator.product_template_form_view +msgid "Configuration Restrictions" +msgstr "Restrictions de configuration" + +#. module: product_configurator +#: model:ir.actions.act_window,name:product_configurator.product_config_session +#: model:ir.ui.menu,name:product_configurator.menu_product_config_session +#: model:ir.ui.view,arch_db:product_configurator.product_config_session_form_view +#: model:ir.ui.view,arch_db:product_configurator.product_config_session_tree_view +msgid "Configuration Sessions" +msgstr "Sessions de configuration" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_line_config_step_id +#: model:ir.ui.view,arch_db:product_configurator.config_step_form_view +#: model:ir.ui.view,arch_db:product_configurator.config_step_tree_view +msgid "Configuration Step" +msgstr "Étape de configuration" + +#. module: product_configurator +#: model:ir.actions.act_window,name:product_configurator.product_config_steps_action +#: model:ir.ui.menu,name:product_configurator.menu_product_config_steps_action +#: model:ir.ui.view,arch_db:product_configurator.product_template_form_view +msgid "Configuration Steps" +msgstr "Étapes de configuration" + +#. module: product_configurator +#: model:ir.ui.view,arch_db:product_configurator.product_attribute_value_custom_form +#: model:ir.ui.view,arch_db:product_configurator.product_attribute_value_custom_tree +msgid "Configuration Values" +msgstr "Valeurs de configuration" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_config.py:491 +#, python-format +msgid "Configuration cannot have the same value inserted twice" +msgstr "Configuration ne peut pas avoir la même valeur insérée deux fois" + +#. module: product_configurator +#: model:ir.ui.view,arch_db:product_configurator.product_template_form_view +msgid "Configurator" +msgstr "Configurateur" + +#. module: product_configurator +#: model:ir.actions.act_window,name:product_configurator.product_configurable_variant_action +msgid "Configured Variants" +msgstr "Variantes configurées" + +#. module: product_configurator +#: code:addons/product_configurator/models/product.py:509 +#, python-format +msgid "Could not convert custom value '%s' to '%s' on product variant: '%s'" +msgstr "Pas pu convertir la valeur personnalisée « %s » à « %s » sur la variante de l'article: « %s »" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_create_uid +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_create_uid +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_create_date +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_create_date +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_create_date +msgid "Created on" +msgstr "Créé le" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_line_custom +#: model:product.attribute,name:product_configurator.custom_attribute +#: model:product.attribute.value,name:product_configurator.custom_attribute_value +msgid "Custom" +msgstr "Personnalisé" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_val_custom +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_value_custom_value +msgid "Custom Value" +msgstr "Valeur personnalisé" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_custom_value_ids +#: model:ir.model.fields,field_description:product_configurator.field_product_product_value_custom_ids +#: model:ir.model.fields,field_description:product_configurator.field_sale_order_line_custom_value_ids +#: model:ir.ui.view,arch_db:product_configurator.product_attribute_form_view +#: model:ir.ui.view,arch_db:product_configurator.product_config_session_form_view +#: model:ir.ui.view,arch_db:product_configurator.product_form_view_custom_vals_inherit +msgid "Custom Values" +msgstr "Valeurs personnalisées" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_config_session_custom_value_value +msgid "Custom value held as string" +msgstr "Valeur personnalisé en texte" + +#. module: product_configurator +#: selection:product.attribute,custom_type:0 +msgid "Date" +msgstr "Date" + +#. module: product_configurator +#: selection:product.attribute,custom_type:0 +msgid "DateTime" +msgstr "DateTime" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_description +msgid "Description" +msgstr "Description" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_required +msgid "Determines the required value of this attribute though it can be change on the template level" +msgstr "Détermine la valeur requise de cette caractéristique, mais il peut être le changement au niveau du modèle" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_value_custom_display_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_display_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_line_display_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_image_display_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_line_display_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_custom_value_display_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_display_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_display_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_line_display_name +msgid "Display Name" +msgstr "Afficher le nom" + +#. module: product_configurator +#: selection:product.config.session,state:0 +msgid "Done" +msgstr "Terminé" + +#. module: product_configurator +#: selection:product.config.session,state:0 +msgid "Draft" +msgstr "Brouillon" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_custom_type +msgid "Field Type" +msgstr "Type du Champ" + +#. module: product_configurator +#: selection:product.attribute,custom_type:0 +msgid "Float" +msgstr "Float" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_id +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_id +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_id +msgid "ID" +msgstr "ID" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_image +#: model:ir.model.fields,field_description:product_configurator.field_product_config_image_image +msgid "Image" +msgstr "Image" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_implied_ids +#: model:ir.ui.view,arch_db:product_configurator.product_config_domain_form_view +msgid "Inherited" +msgstr "Hérité" + +#. module: product_configurator +#: selection:product.attribute,custom_type:0 +msgid "Integer" +msgstr "Integer" + +#. module: product_configurator +#: code:addons/product_configurator/models/product.py:347 +#: code:addons/product_configurator/models/product_config.py:439 +#, python-format +msgid "Invalid Configuration" +msgstr "Configuration non valide" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_account_invoice_line +msgid "Invoice Line" +msgstr "ligne de facturation" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_line_required +msgid "Is this attribute required?" +msgstr "Caractéristique requise?" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_value_custom___last_update +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain___last_update +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_line___last_update +#: model:ir.model.fields,field_description:product_configurator.field_product_config_image___last_update +#: model:ir.model.fields,field_description:product_configurator.field_product_config_line___last_update +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session___last_update +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_custom_value___last_update +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step___last_update +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_line___last_update +msgid "Last Modified on" +msgstr "Dernière Modification le" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_write_uid +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_write_uid +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_write_date +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_write_date +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_max_val +msgid "Max Value" +msgstr "Valeur maximale" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_min_val +msgid "Min Value" +msgstr "Valeur minimale" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_max_val +#: model:ir.model.fields,help:product_configurator.field_product_attribute_min_val +msgid "Minimum value allowed" +msgstr "Valeur minimale permise" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_line_multi +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_multi +msgid "Multi" +msgstr "Multi" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_value_custom_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_image_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_line_name +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_name +#: model:ir.model.fields,field_description:product_configurator.field_product_product_config_name +msgid "Name" +msgstr "Nom" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_line_operator +msgid "Operators" +msgstr "Opérateurs" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_price +msgid "Price" +msgstr "Prix" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_product +#: model:ir.model.fields,field_description:product_configurator.field_product_config_image_product_tmpl_id +msgid "Product" +msgstr "Article" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_attribute +msgid "Product Attribute" +msgstr "Caractéristique de l'article" + +#. module: product_configurator +#: model:ir.ui.view,arch_db:product_configurator.product_attribute_value_form_view +msgid "Product Attribute Values" +msgstr "Valeurs de caractéristique de l'article" + +#. module: product_configurator +#: model:ir.module.category,name:product_configurator.product_config_category +#: model:ir.ui.view,arch_db:product_configurator.product_attribute_form_view +msgid "Product Configurator" +msgstr "Configurateur de produits" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_value_custom_product_id +msgid "Product ID" +msgstr "Article ID" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_template +#: model:ir.model.fields,field_description:product_configurator.field_product_config_line_product_tmpl_id +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_line_product_tmpl_id +msgid "Product Template" +msgstr "Modèle de produit" + +#. module: product_configurator +#: model:res.groups,name:product_configurator.group_product_configurator +msgid "Products" +msgstr "Articles" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_value_product_id +msgid "Related Product" +msgstr "Articles connexes" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_line_required +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_required +msgid "Required" +msgstr "Requis" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_domain_line_ids +#: model:ir.model.fields,field_description:product_configurator.field_product_config_line_domain_id +msgid "Restrictions" +msgstr "Restrictions" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_product_reuse_variant +#: model:ir.model.fields,field_description:product_configurator.field_product_template_reuse_variant +msgid "Reuse variants if exists" +msgstr "Réutiliser les variantes qui existent" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_line_domain_id +msgid "Rule" +msgstr "Règle" + +#. module: product_configurator +#: model:ir.ui.view,arch_db:product_configurator.product_config_domain_form_view +msgid "Rules" +msgstr "Règles" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_sale_order_line +msgid "Sales Order Line" +msgstr "Ligne de bons de commande" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_search_ok +msgid "Searchable" +msgstr "Consultable" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_attribute.py:108 +#, python-format +msgid "Selected custom field type '%s' is not searchable" +msgstr "Type de champ personnalisé sélectionné « %s » n’est pas consultable" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_attribute.py:129 +#, python-format +msgid "Selected custom value '%s' must be at least %s" +msgstr "Valeur personnalisée sélectionnée « %s » doit être au moins %s" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_attribute.py:124 +#, python-format +msgid "Selected custom value '%s' must be between %s and %s" +msgstr "Valeur personnalisée sélectionnée « %s » doit être comprise entre %s et %s" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_attribute.py:134 +#, python-format +msgid "Selected custom value '%s' must be lower than %s" +msgstr "Valeur personnalisée sélectionnée « %s » doit être inférieure à %s" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_line_sequence +#: model:ir.model.fields,field_description:product_configurator.field_product_config_image_sequence +#: model:ir.model.fields,field_description:product_configurator.field_product_config_line_sequence +#: model:ir.model.fields,field_description:product_configurator.field_product_config_step_line_sequence +msgid "Sequence" +msgstr "Séquence" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_custom_value_cfg_session_id +msgid "Session" +msgstr "Session" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_state +msgid "State" +msgstr "État" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_stock_move +msgid "Stock Move" +msgstr "Mouvement de stock" + +#. module: product_configurator +#: selection:product.attribute,custom_type:0 +msgid "Textarea" +msgstr "Textarea" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_custom_type +msgid "The type of the custom field generated in the frontend" +msgstr "Le type de champ personnalisé généré dans le frontend" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_trans_implied_ids +msgid "Transitively inherits" +msgstr "Hérite transitivement" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_attribute_uom_id +msgid "Unit of Measure" +msgstr "Unité de mesure" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_user_id +msgid "User" +msgstr "Utilisateur" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_create_on_fly +msgid "User can create new value with product configurator" +msgstr "Utilisateur peut créer de nouvelle valeur avec le configurateur de produit" + +#. module: product_configurator +#: model:ir.ui.view,arch_db:product_configurator.product_attribute_form_view +msgid "Validation" +msgstr "Validation" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_custom_value_value +#: model:ir.ui.view,arch_db:product_configurator.product_attribute_value_form_view +msgid "Value" +msgstr "Valeur" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_session_value_ids +msgid "Value ids" +msgstr "Value ids" + +#. module: product_configurator +#: model:ir.model.fields,field_description:product_configurator.field_product_config_domain_line_value_ids +#: model:ir.model.fields,field_description:product_configurator.field_product_config_line_value_ids +msgid "Values" +msgstr "Valeurs" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_config.py:214 +#, python-format +msgid "Values entered for line '%s' generate a incompatible configuration" +msgstr "Les valeurs entrées pour la ligne « %s » génèrent une configuration incompatible" + +#. module: product_configurator +#: code:addons/product_configurator/models/product_config.py:177 +#, python-format +msgid "Values must belong to the attribute of the corresponding attribute_line set on the configuration line" +msgstr "Les valeurs doivent appartenir à la caractéristique correspondante sur la ligne de configuration" + +#. module: product_configurator +#: model:ir.model.fields,help:product_configurator.field_product_attribute_search_ok +msgid "When checking for variants with the same configuration, do we include this field in the search?" +msgstr "Lors de la vérification des variantes avec la même configuration, devons-nous inclure ce champ dans la recherche ?" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_attribute_line +msgid "product.attribute.line" +msgstr "product.attribute.line" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_attribute_value +msgid "product.attribute.value" +msgstr "product.attribute.value" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_attribute_value_custom +msgid "product.attribute.value.custom" +msgstr "product.attribute.value.custom" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_config_domain +msgid "product.config.domain" +msgstr "product.config.domain" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_config_domain_line +msgid "product.config.domain.line" +msgstr "product.config.domain.line" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_config_image +msgid "product.config.image" +msgstr "product.config.image" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_config_line +msgid "product.config.line" +msgstr "product.config.line" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_config_session +msgid "product.config.session" +msgstr "product.config.session" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_config_session_custom_value +msgid "product.config.session.custom.value" +msgstr "product.config.session.custom.value" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_config_step +msgid "product.config.step" +msgstr "product.config.step" + +#. module: product_configurator +#: model:ir.model,name:product_configurator.model_product_config_step_line +msgid "product.config.step.line" +msgstr "product.config.step.line" diff --git a/product_configurator/models/account.py b/product_configurator/models/account.py index 7d8d2a60..d8ec99b6 100644 --- a/product_configurator/models/account.py +++ b/product_configurator/models/account.py @@ -6,4 +6,4 @@ class AccountInvoiceLine(models.Model): _inherit = 'account.invoice.line' - product_id = fields.Many2one(domain=[('config_ok', '=', False)]) + product_id = fields.Many2one(domain=['|', ('reuse_variant', '=', True), ('config_ok', '=', False)]) diff --git a/product_configurator/models/product.py b/product_configurator/models/product.py index 9a6bfe56..7f48d674 100644 --- a/product_configurator/models/product.py +++ b/product_configurator/models/product.py @@ -11,12 +11,20 @@ class ProductTemplate(models.Model): config_ok = fields.Boolean(string='Can be Configured') + reuse_variant = fields.Boolean(string='Reuse variants if exists') + config_line_ids = fields.One2many( comodel_name='product.config.line', inverse_name='product_tmpl_id', string="Attribute Dependencies" ) + config_default_ids = fields.One2many( + comodel_name='product.config.default', + inverse_name='product_tmpl_id', + string="Attribute Defaults" + ) + config_image_ids = fields.One2many( comodel_name='product.config.image', inverse_name='product_tmpl_id', @@ -439,6 +447,44 @@ def values_available(self, attr_val_ids, sel_val_ids): return avail_val_ids + @api.multi + def find_default_value(self, selectable_value_ids, value_ids): + """Based on the current values, which of the available template value ids + is the best default value to use. + + :param selectable_value_ids: list of product.attribute.value + object already trimmed down as selectable, for one + attribute line. + :param value_ids: list of attribute value ids already chosen + + :returns: The first matched default id + + """ + self.ensure_one() + + if not selectable_value_ids: + return False + # assume all values are from the same attribute line - they should be! + default_lines = self.config_default_ids.filtered( + lambda l: set(l.value_ids.ids) & set(selectable_value_ids) + ) + + for default_line in default_lines: + if not default_line.domain_id: + # No domain - always considered true. Use this. + break + domains = default_line.mapped('domain_id').compute_domain() + if self.validate_domains_against_sels(domains, value_ids): + # Domain OK, use this + break + else: + # parsed all lines without a match + return False + # pick one at random... + return ( + set(default_line.value_ids.ids) & set(selectable_value_ids) + ).pop() + @api.multi def validate_configuration(self, value_ids, custom_vals=None, final=True): """ Verifies if the configuration values passed via value_ids and custom_vals diff --git a/product_configurator/models/product_attribute.py b/product_configurator/models/product_attribute.py index 9ec1dba5..b9684bd4 100644 --- a/product_configurator/models/product_attribute.py +++ b/product_configurator/models/product_attribute.py @@ -90,6 +90,11 @@ def onchange_custom_type(self): image = fields.Binary(string='Image') + create_on_fly = fields.Boolean( + string='Can create value on the fly', + help='User can create new value with product configurator' + ) + # TODO prevent the same attribute from being defined twice on the # attribute lines @@ -167,6 +172,27 @@ def onchange_attribute(self): class ProductAttributeValue(models.Model): _inherit = 'product.attribute.value' + @api.model + def create(self, vals): + if self.env.context.get('product_tmpl_id'): + # intercept already-created value + product_tmpl_id = self.env.context.get('product_tmpl_id') + attribute_id = vals.get('attribute_id') + line = self.env['product.attribute.line'].search([ + ('product_tmpl_id', '=', product_tmpl_id), + ('attribute_id', '=', attribute_id)]) + match = line.attribute_id.value_ids.filtered(lambda rec: rec.name == vals['name']) + if match: + record = match[0] + else: + # default behavior + record = super(ProductAttributeValue, self).create(vals) + # create related line + line.value_ids += record + else: + record = super(ProductAttributeValue, self).create(vals) + return record + @api.multi def copy(self, default=None): default.update({'name': self.name + " (copy)"}) diff --git a/product_configurator/models/product_config.py b/product_configurator/models/product_config.py index 64ae1a31..bf723bed 100644 --- a/product_configurator/models/product_config.py +++ b/product_configurator/models/product_config.py @@ -197,6 +197,59 @@ def check_value_attributes(self): ) +class ProductConfigDefault(models.Model): + _name = 'product.config.default' + + product_tmpl_id = fields.Many2one( + comodel_name='product.template', + string='Product Template', + ondelete='cascade', + required=True + ) + + # TODO: Find a more elegant way to restrict the value_ids + attr_line_val_ids = fields.Many2many( + comodel_name='product.attribute.value', + compute='_compute_attr_vals' + ) + + value_ids = fields.Many2many( + comodel_name='product.attribute.value', + id1="cfg_dflt_id", + id2="attr_val_id", + string="Values" + ) + + domain_id = fields.Many2one( + comodel_name='product.config.domain', + string='Applied If', + help='Default will be attempted if this rule passes, or leave blank ' + 'for a generic default' + ) + + sequence = fields.Integer(string='Sequence', default=10) + + _order = 'product_tmpl_id, sequence, id' + + @api.multi + def _compute_attr_vals(self): + for config_default in self: + config_default.attr_line_val_ids = \ + config_default.product_tmpl_id.attribute_line_ids.mapped( + 'value_ids' + ) + + @api.model + def default_get(self, fields): + result = super(ProductConfigDefault, self).default_get(fields) + if self.env.context.get('for_template_id'): + result['attr_line_val_ids'] = \ + self.env['product.template'].browse( + self.env.context['for_template_id'] + ).attribute_line_ids.mapped('value_ids').ids + return result + + class ProductConfigImage(models.Model): _name = 'product.config.image' diff --git a/product_configurator/models/sale.py b/product_configurator/models/sale.py index 46c95cec..cd7bb993 100644 --- a/product_configurator/models/sale.py +++ b/product_configurator/models/sale.py @@ -20,4 +20,4 @@ class SaleOrderLine(models.Model): string="Custom Values" ) - product_id = fields.Many2one(domain=[('config_ok', '=', False)]) + product_id = fields.Many2one(domain=['|', ('reuse_variant', '=', True), ('config_ok', '=', False)]) diff --git a/product_configurator/models/stock.py b/product_configurator/models/stock.py index 0eb9ef68..ecb62ccf 100644 --- a/product_configurator/models/stock.py +++ b/product_configurator/models/stock.py @@ -6,4 +6,4 @@ class StockMove(models.Model): _inherit = 'stock.move' - product_id = fields.Many2one(domain=[('config_ok', '=', False)]) + product_id = fields.Many2one(domain=['|', ('reuse_variant', '=', True), ('config_ok', '=', False)]) diff --git a/product_configurator/security/ir.model.access.csv b/product_configurator/security/ir.model.access.csv index 5d1d44e2..e21b3421 100644 --- a/product_configurator/security/ir.model.access.csv +++ b/product_configurator/security/ir.model.access.csv @@ -1,5 +1,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink product_configurator_config_line,Config Line,model_product_config_line,group_product_configurator,1,1,1,1 +product_configurator_config_default,Config Default,model_product_config_default,group_product_configurator,1,1,1,1 product_configurator_config_image,Config Image,model_product_config_image,group_product_configurator,1,1,1,1 product_configurator_config_step,Config Step,model_product_config_step,group_product_configurator,1,1,1,1 product_configurator_config_step_line,Config Step Line,model_product_config_step_line,group_product_configurator,1,1,1,1 @@ -10,6 +11,7 @@ product_configurator_config_session,Config Session,model_product_config_session, product_configurator_config_session_custom_value,Config Session Custom Value,model_product_config_session_custom_value,group_product_configurator,1,1,1,1 ,,,,,,, user_config_line,User Config Line,model_product_config_line,base.group_user,1,0,0,0 +user_config_default,User Config Default,model_product_config_default,base.group_user,1,0,0,0 user_config_image,User Config Image,model_product_config_image,base.group_user,1,0,0,0 user_config_step,User Config Step,model_product_config_step,base.group_user,1,0,0,0 user_config_step_line,User Config Step Line,model_product_config_step_line,base.group_user,1,0,0,0 @@ -25,6 +27,7 @@ portal_config_step,Portal Config Step,model_product_config_step,base.group_porta portal_config_session,Portal Config Session,model_product_config_session,base.group_portal,1,0,0,0 portal_config_session_custom_value,Portal Config Session Custom Value,model_product_config_session_custom_value,base.group_portal,1,0,0,0 portal_configurator_config_line,Portal Config Line,model_product_config_line,base.group_portal,1,0,0,0 +portal_configurator_config_default,Portal Config Default,model_product_config_default,base.group_portal,1,0,0,0 portal_configurator_config_step_line,Portal Config Step Line,model_product_config_step_line,base.group_portal,1,0,0,0 portal_configurator_config_domain,Portal Config Domain,model_product_config_domain,base.group_portal,1,0,0,0 portal_configurator_config_domain_line,Portal Config Domain Line,model_product_config_domain_line,base.group_portal,1,0,0,0 diff --git a/product_configurator/tests/test_configuration_rules.py b/product_configurator/tests/test_configuration_rules.py index 984a3010..feac814e 100644 --- a/product_configurator/tests/test_configuration_rules.py +++ b/product_configurator/tests/test_configuration_rules.py @@ -101,4 +101,41 @@ def test_invalid_custom_value_configuration(self): self.assertFalse(validation, "Custom value accepted for fixed " "attribute color") - # TODO: Test configuration with disallowed custom type value + def test_configuration_defaults(self): + conf = ['gasoline', 'tapistry_black'] + engine_selections = self.env.ref( + 'product_configurator.product_config_line_gasoline_engines' + ) + attr_val_ids = self.get_attr_val_ids(conf) + default_value_engine = self.cfg_tmpl.find_default_value( + engine_selections.value_ids.ids, + attr_val_ids, + ) + self.assertEqual( + [default_value_engine], self.get_attr_val_ids(['218i']), + "Gasoline Engine default not set correctly" + ) + + color_selection_ids = self.get_attr_val_ids(['red', 'silver', 'black']) + attr_val_ids = self.get_attr_val_ids(conf) + default_value_color = self.cfg_tmpl.find_default_value( + color_selection_ids, + attr_val_ids, + ) + self.assertEqual( + [default_value_color], self.get_attr_val_ids(['red']), + "Gasoline Color default not set correctly" + ) + + color_selection_ids = self.get_attr_val_ids(['silver', 'black']) + attr_val_ids = self.get_attr_val_ids(conf) + default_value_color = self.cfg_tmpl.find_default_value( + color_selection_ids, + attr_val_ids, + ) + self.assertFalse( + default_value_color, + "Gasoline Color should not have been returned unselectable value" + ) + + # Test configuration with disallowed custom type value diff --git a/product_configurator/views/product_attribute_view.xml b/product_configurator/views/product_attribute_view.xml index bf373967..27f7ad98 100644 --- a/product_configurator/views/product_attribute_view.xml +++ b/product_configurator/views/product_attribute_view.xml @@ -52,6 +52,7 @@ + diff --git a/product_configurator/views/product_view.xml b/product_configurator/views/product_view.xml index 1519dece..a7ca2dd2 100644 --- a/product_configurator/views/product_view.xml +++ b/product_configurator/views/product_view.xml @@ -43,6 +43,9 @@ + + +