Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

10.0 test name [rappel!] #31

Open
wants to merge 67 commits into
base: 10.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
6c9b989
[FIX] Add support for the sale_margin module
matt454357 Apr 10, 2017
a897545
Pass single dict to update method
matt454357 Apr 11, 2017
94d052b
Create new module to add product_configurator to purchase
elemire Mar 23, 2017
da89fd4
Move some code so that the Wizard mode can run without purchase module
elemire Mar 23, 2017
7f85dda
Add missing files for purchase
elemire Mar 24, 2017
8ff8854
Fix problem with date_palnned for purchase
elemire Apr 12, 2017
9e11791
fix date planned
elemire Apr 12, 2017
1a92236
product_configurator_name
coleste Apr 19, 2017
37a850b
fix variant name for attributes with restricted chars .:
coleste Apr 20, 2017
62e33d0
[FIX] Add support for the sale_margin module
matt454357 Apr 10, 2017
1c63da6
Pass single dict to update method
matt454357 Apr 11, 2017
8fd4cec
[FIX] Add support for the sale_margin module
matt454357 Apr 10, 2017
ad76678
Create new module to add product_configurator to purchase
elemire Mar 23, 2017
8cf80ae
Move some code so that the Wizard mode can run without purchase module
elemire Mar 23, 2017
7315133
Add missing files for purchase
elemire Mar 24, 2017
6dade66
Fix problem with date_palnned for purchase
elemire Apr 12, 2017
5d81995
fix date planned
elemire Apr 12, 2017
1a61b58
[FIX] Add support for the sale_margin module
matt454357 Apr 10, 2017
15fe06d
Create new module to add product_configurator to purchase
elemire Mar 23, 2017
0f04245
Move some code so that the Wizard mode can run without purchase module
elemire Mar 23, 2017
e0a3307
Add missing files for purchase
elemire Mar 24, 2017
4cc83ee
create attribute values from configurator
coleste Apr 5, 2017
bea2012
create attribute value on the fly
elemire Apr 12, 2017
1c2cea8
Merge branch '10.0' into 10.0-product_configurator_name
elemire Apr 21, 2017
dc83db5
Merge branch '10.0-create-variant-values' into 10.0-mic
elemire Apr 21, 2017
f1969c0
Merge branch '10.0-product_configurator_name' into 10.0-mic
elemire Apr 21, 2017
0e338fd
Merge error
elemire Apr 21, 2017
f61bc36
Add name_override to variant easy form
elemire Apr 21, 2017
286d46f
Merge branch '10.0-product_configurator_name' into 10.0-mic
elemire Apr 21, 2017
f217397
Add name_override to variant normal form
elemire Apr 21, 2017
234e142
Merge branch '10.0-product_configurator_name' into 10.0-mic
elemire Apr 21, 2017
a95eda4
Created new menus for product configutors in purchase and inventory
dhukaasif Apr 28, 2017
925fcd8
ENH - Default Values based on domains.
Apr 5, 2017
b51df94
New tests, and PEP8 code fixes.
Apr 10, 2017
5e2676b
PEP8 checks.
Apr 10, 2017
30fdbb1
Changes to use enhanced domain validation for defaults.
Apr 25, 2017
996982c
ENH - Multi call to onchange domain after defaults set.
Apr 30, 2017
e0b8790
Correct parameter passig
Apr 30, 2017
8ceb23c
Test updated.
May 4, 2017
37a6768
Deal with multi selects correctly in recursive onchange
May 5, 2017
0884e7a
Copy Attributes and values menus from sale to purchase
elemire May 30, 2017
605335a
Add menu products in purchase congiguration
elemire May 30, 2017
025c972
fix single-value variant
coleste May 30, 2017
0360c6e
Change display_mode name
elemire May 30, 2017
5cf0ec9
Merge pull request #1 from microcom/10.0-fix-variant-none
elemire May 30, 2017
435d559
allow reuse_variant products
coleste May 30, 2017
d12857f
Merge pull request #2 from microcom/10.0-allow-reuse
elemire May 30, 2017
af17a39
translation
coleste May 30, 2017
f2476f2
Merge pull request #4 from microcom/10.0-translation
elemire May 31, 2017
9cac2aa
Made sequence field invisible
dhukaasif Jun 2, 2017
311b678
Fix name bug, when no values for an attribute
elemire Jun 5, 2017
59d8161
Merge pull request #5 from microcom/10.0-fix-name
elemire Jun 5, 2017
2ce678b
add display/hidden to tree
coleste Jun 6, 2017
9d19d1c
fix problem with purchase & modify product by configurator
elemire Jun 8, 2017
874e353
Merge pull request #6 from microcom/10.0-name-column
elemire Jun 8, 2017
b59d86e
[Fix] ensure multi selects dealt with consistently during default eva…
Jun 8, 2017
8c2a779
Fix description
elemire Jun 15, 2017
9c3467e
remove unused code
elemire Jun 15, 2017
57e5a46
Merge pull request #7 from microcom/10.0-fix-po-description
elemire Jun 15, 2017
3fc9ee6
Merge branch '10.0-mic' into 10.0-hide_attribute_sequence
elemire Jun 28, 2017
7e31f95
Merge pull request #8 from microcom/10.0-hide_attribute_sequence
elemire Jun 28, 2017
eb94e63
[FIX] Add support for the sale_margin module
matt454357 Apr 10, 2017
36e1a43
Pass single dict to update method
matt454357 Apr 11, 2017
cb1378a
Merge branch '10.0' into 10.0-mic
elemire Jun 28, 2017
ef6f53e
Merge branch '10.0-domain-based-defaults' into 10.0-mic
coleste Jun 28, 2017
7d9d3c6
add tests to name module
coleste Jul 5, 2017
1ce059e
cleanup name module
coleste Jul 5, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions product_configurator/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
],
Expand Down
20 changes: 20 additions & 0 deletions product_configurator/demo/product_config_defaults.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="product_config_default_gasoline_engines" model="product.config.default">
<field name="product_tmpl_id" ref="bmw_2_series"/>
<field name="value_ids" eval="[(6, 0, [
ref('product_attribute_value_218i'),
ref('product_attribute_value_red'),
])]"/>
<field name="domain_id" ref="product_config_domain_gasoline"/>
</record>

<record id="product_config_default_diesel_engines" model="product.config.default">
<field name="product_tmpl_id" ref="bmw_2_series"/>
<field name="value_ids" eval="[(6, 0, [
ref('product_attribute_value_218d'),
ref('product_attribute_value_black'),
])]"/>
<field name="domain_id" ref="product_config_domain_diesel"/>
</record>
</odoo>
704 changes: 704 additions & 0 deletions product_configurator/i18n/fr_CA.po

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion product_configurator/models/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)])
46 changes: 46 additions & 0 deletions product_configurator/models/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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
Expand Down
26 changes: 26 additions & 0 deletions product_configurator/models/product_attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)"})
Expand Down
53 changes: 53 additions & 0 deletions product_configurator/models/product_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down
2 changes: 1 addition & 1 deletion product_configurator/models/sale.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)])
2 changes: 1 addition & 1 deletion product_configurator/models/stock.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)])
3 changes: 3 additions & 0 deletions product_configurator/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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
39 changes: 38 additions & 1 deletion product_configurator/tests/test_configuration_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions product_configurator/views/product_attribute_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<group>
<field name="custom_type"/>
<field name="search_ok"/>
<field name="create_on_fly" />
</group>
<group>
<field name="min_val" attrs="{'invisible': [('custom_type','not in',['int','float'])]}"/>
Expand Down
21 changes: 21 additions & 0 deletions product_configurator/views/product_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
<!-- TODO: Apply domains so only values from template are available -->
<xpath expr="//notebook/page[@name='variants']" position="after">
<page string="Configurator" attrs="{'invisible': [('config_ok','=',False)]}">
<separator colspan="4" string="Configuration Options"/>
<field name="reuse_variant"/>
<label for="reuse_variant"/>
<separator colspan="4" string="Configuration Restrictions"/>
<field name="config_line_ids"
attrs="{'readonly': [('attribute_line_ids','=',[])]}"
Expand All @@ -65,6 +68,24 @@
<field name="domain_id"/>
</tree>
</field>
<separator colspan="4" string="Configuration Defaults"/>
<field name="config_default_ids"
attrs="{'readonly': [('attribute_line_ids','=',[])]}"
context="{'show_attribute': True, 'for_template_id': id}">
<tree string="Attribute Value Defaults" editable="bottom">
<field name="sequence" widget="handle"/>
<field name="domain_id"/>
<!-- # TODO: Find a more elegant way to restrict the value_ids -->
<field name="attr_line_val_ids"
widget="many2many_tags"
invisible="True"/>
<field name="value_ids"
widget="many2many_tags"
domain="[('id','in',attr_line_val_ids[0][2])]"
options="{'no_create': True, 'no_create_edit': True}"
context="{'show_attribute': True}"/>
</tree>
</field>
<separator colspan="4" string="Configuration Steps"/>
<field name="config_step_line_ids"
attrs="{'readonly': [('attribute_line_ids','=',[])]}">
Expand Down
14 changes: 14 additions & 0 deletions product_configurator_name/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#Odoo Product Configurator Name

This module is an extension to product configurator to hide unnecessary attributes from product name
and show the attribute name as label when ambiguities might arise.

Features
========

- Add display mode to comfigurable templates attributes (under variants tab)

Usage
=====

Change the display mode of the attribute to hide or with label as needed.
4 changes: 4 additions & 0 deletions product_configurator_name/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-

from . import models
from . import tests
27 changes: 27 additions & 0 deletions product_configurator_name/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-

{
'name': 'Product Configurator Name',
'version': '10.0',
'category': 'Generic Modules/Base',
'summary': 'product configuration interface for name',
'description': """
Purchase Product Configurator
""",
'author': 'Microcom',
'license': 'AGPL-3',
'website': 'http://www.microcom.ca/',
'depends': [
'product_configurator',
],
"data": [
'views/product_view.xml',
],
'demo': [
],
'images': [
],
'test': [],
'installable': True,
'auto_install': False,
}
Loading