[PATCH] Upstream patch - 24082022

This commit is contained in:
Parthiv Patel
2022-08-24 08:34:37 +00:00
parent 0dc77394d0
commit 91fbd3cccd
6 changed files with 80 additions and 48 deletions
+6 -1
View File
@@ -424,7 +424,12 @@ class ProductProduct(models.Model):
For convenience the template is copied instead and its first variant is
returned.
"""
return self.product_tmpl_id.copy(default=default).product_variant_id
# copy variant is disabled in https://github.com/flectra/flectra/pull/38303
# this returns the first possible combination of variant to make it
# works for now, need to be fixed to return product_variant_id if it's
# possible in the future
template = self.product_tmpl_id.copy(default=default)
return template.product_variant_id or template._create_first_product_variant()
@api.model
def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None):
+12
View File
@@ -975,6 +975,18 @@ class ProductTemplate(models.Model):
'product_template_attribute_value_ids': [(6, 0, combination._without_no_variant_attributes().ids)]
})
def _create_first_product_variant(self, log_warning=False):
"""Create if necessary and possible and return the first product
variant for this template.
:param log_warning: whether a warning should be logged on fail
:type log_warning: bool
:return: the first product variant or none
:rtype: recordset of `product.product`
"""
return self._create_product_variant(self._get_first_possible_combination(), log_warning)
@tools.ormcache('self.id', 'frozenset(filtered_combination.ids)')
def _get_variant_id_for_combination(self, filtered_combination):
"""See `_get_variant_for_combination`. This method returns an ID
+25
View File
@@ -213,6 +213,31 @@ class TestVariants(common.TestProductCommon):
self.assertEqual(variant_copy.name, 'Test Copy (copy) (copy)')
self.assertEqual(len(variant_copy.product_variant_ids), 2)
def test_dynamic_variants_copy(self):
self.color_attr = self.env['product.attribute'].create({'name': 'Color', 'create_variant': 'dynamic'})
self.color_attr_value_r = self.env['product.attribute.value'].create({'name': 'Red', 'attribute_id': self.color_attr.id})
self.color_attr_value_b = self.env['product.attribute.value'].create({'name': 'Blue', 'attribute_id': self.color_attr.id})
# test copy of variant with dynamic attribute
template_dyn = self.env['product.template'].create({
'name': 'Test Dynamical',
'attribute_line_ids': [(0, 0, {
'attribute_id': self.color_attr.id,
'value_ids': [(4, self.color_attr_value_r.id), (4, self.color_attr_value_b.id)],
})]
})
self.assertEqual(len(template_dyn.product_variant_ids), 0)
self.assertEqual(template_dyn.name, 'Test Dynamical')
variant_dyn = template_dyn._create_product_variant(template_dyn._get_first_possible_combination())
self.assertEqual(len(template_dyn.product_variant_ids), 1)
variant_dyn_copy = variant_dyn.copy()
template_dyn_copy = variant_dyn_copy.product_tmpl_id
self.assertEqual(len(template_dyn_copy.product_variant_ids), 1)
self.assertEqual(template_dyn_copy.name, 'Test Dynamical (copy)')
def test_standard_price(self):
""" Ensure template values are correctly (re)computed depending on the context """
one_variant_product = self.product_1
+22 -16
View File
@@ -37,7 +37,12 @@ class XlsxCreatorCase(common.HttpCase):
}
def _mock_write(self, row, column, value, style=None):
self.worksheet[row, column] = str(value)
if isinstance(value, float):
decimal_places = style.num_format[::-1].find('.')
style_format = "{:." + str(decimal_places) + "f}"
self.worksheet[row, column] = style_format.format(value)
else:
self.worksheet[row, column] = str(value)
def make(self, values, context=None):
return self.model.with_context(**(context or {})).create(values)
@@ -79,6 +84,7 @@ class XlsxCreatorCase(common.HttpCase):
@tagged('-at_install', 'post_install')
class TestGroupedExport(XlsxCreatorCase):
model_name = 'export.group_operator'
# pylint: disable=bad-whitespace
def test_int_sum_max(self):
values = [
@@ -125,12 +131,12 @@ class TestGroupedExport(XlsxCreatorCase):
['Int Sum' ,'Float Min'],
['10 (2)' ,'111.00'],
[' 111.0 (1)','111.00'],
['10' ,'111.0'],
['10' ,'111.00'],
[' 222.0 (1)','222.00'],
['10' ,'222.0'],
['10' ,'222.00'],
['20 (1)' ,'333.00'],
[' 333.0 (1)','333.00'],
['20' ,'333.0'],
['20' ,'333.00'],
])
def test_float_avg(self):
@@ -145,12 +151,12 @@ class TestGroupedExport(XlsxCreatorCase):
['Int Sum' ,'Float Avg'],
['10 (2)' ,'150.00'],
[' 100.0 (1)','100.00'],
['10' ,'100.0'],
['10' ,'100.00'],
[' 200.0 (1)','200.00'],
['10' ,'200.0'],
['10' ,'200.00'],
['20 (1)' ,'300.00'],
[' 300.0 (1)','300.00'],
['20' ,'300.0'],
['20' ,'300.00'],
])
def test_float_avg_nested(self):
@@ -167,12 +173,12 @@ class TestGroupedExport(XlsxCreatorCase):
['10 (3)' ,'300.00'],
[' 20 (1)' ,'600.00'],
[' 600.0 (1)','600.00'],
['10' ,'600.0'],
['10' ,'600.00'],
[' 30 (2)' ,'150.00'],
[' 100.0 (1)','100.00'],
['10' ,'100.0'],
['10' ,'100.00'],
[' 200.0 (1)','200.00'],
['10' ,'200.0'],
['10' ,'200.00'],
])
def test_float_avg_nested_no_value(self):
@@ -189,11 +195,11 @@ class TestGroupedExport(XlsxCreatorCase):
['10 (3)' ,'0.00'],
[' 20 (1)' ,'0.00'],
[' Undefined (1)','0.00'],
['10' ,'0.0'],
['10' ,'0.00'],
[' 30 (2)' ,'0.00'],
[' Undefined (2)','0.00'],
['10' ,'0.0'],
['10' ,'0.0'],
['10' ,'0.00'],
['10' ,'0.00'],
])
def test_date_max(self):
@@ -367,13 +373,13 @@ class TestGroupedExport(XlsxCreatorCase):
['Int Sum', 'Float Monetary'],
['1 (1)','60739.200'],
[' 60739.2 (1)','60739.200'],
['1','60739.2'],
['1','60739.20'],
['2 (1)','2.000'],
[' 2.0 (1)','2.000'],
['2','2.0'],
['2','2.00'],
['3 (1)','1000.000'],
[' 1000.0 (1)','1000.000'],
['3','1000.0'],
['3','1000.00'],
])
@tagged('-at_install', 'post_install')
+15 -19
View File
@@ -34,10 +34,10 @@ import flectra
import flectra.modules.registry
from flectra.api import call_kw, Environment
from flectra.modules import get_module_path, get_resource_path
from flectra.tools import image_process, topological_sort, html_escape, pycompat, ustr, apply_inheritance_specs, lazy_property, float_repr
from flectra.tools import image_process, topological_sort, html_escape, pycompat, ustr, apply_inheritance_specs, lazy_property
from flectra.tools.mimetypes import guess_mimetype
from flectra.tools.translate import _
from flectra.tools.misc import str2bool, xlsxwriter, file_open
from flectra.tools.misc import str2bool, xlsxwriter, file_open, get_lang
from flectra.tools.safe_eval import safe_eval, time
from flectra import http, tools
from flectra.http import content_disposition, dispatch_rpc, request, serialize_exception as _serialize_exception, Response
@@ -777,6 +777,10 @@ class ExportXlsxWriter:
self.datetime_style = self.workbook.add_format({'text_wrap': True, 'num_format': 'yyyy-mm-dd hh:mm:ss'})
self.worksheet = self.workbook.add_worksheet()
self.value = False
decimal_separator = get_lang(request.env).decimal_point
self.float_format = f'0{decimal_separator}00'
decimal_places = [res['decimal_places'] for res in request.env['res.currency'].search_read([], ['decimal_places'])]
self.monetary_format = f'0{decimal_separator}{max(decimal_places or [2]) * "0"}'
if row_count > self.worksheet.xls_rowmax:
raise UserError(_('There are too many rows (%s rows, limit: %s) to export as Excel 2007-2013 (.xlsx) format. Consider splitting the export.') % (row_count, self.worksheet.xls_rowmax))
@@ -824,6 +828,8 @@ class ExportXlsxWriter:
cell_style = self.datetime_style
elif isinstance(cell_value, datetime.date):
cell_style = self.date_style
elif isinstance(cell_value, float):
cell_style.set_num_format(self.float_format)
elif isinstance(cell_value, (list, tuple)):
cell_value = pycompat.to_text(cell_value)
self.write(row, column, cell_value, cell_style)
@@ -859,26 +865,16 @@ class GroupExportXlsxWriter(ExportXlsxWriter):
label = '%s%s (%s)' % (' ' * group_depth, label, group.count)
self.write(row, column, label, self.header_bold_style)
if any(f.get('type') == 'monetary' for f in self.fields[1:]):
decimal_places = [res['decimal_places'] for res in group._model.env['res.currency'].search_read([], ['decimal_places'])]
decimal_places = max(decimal_places) if decimal_places else 2
for field in self.fields[1:]: # No aggregates allowed in the first column because of the group title
column += 1
aggregated_value = aggregates.get(field['name'])
# Float fields may not be displayed properly because of float
# representation issue with non stored fields or with values
# that, even stored, cannot be rounded properly and it is not
# acceptable to display useless digits (i.e. monetary)
#
# non stored field -> we force 2 digits
# stored monetary -> we force max digits of installed currencies
if isinstance(aggregated_value, float):
if field.get('type') == 'monetary':
aggregated_value = float_repr(aggregated_value, decimal_places)
elif not field.get('store'):
aggregated_value = float_repr(aggregated_value, 2)
self.write(row, column, str(aggregated_value if aggregated_value is not None else ''), self.header_bold_style)
if field.get('type') == 'monetary':
self.header_bold_style.set_num_format(self.monetary_format)
elif field.get('type') == 'float':
self.header_bold_style.set_num_format(self.float_format)
else:
aggregated_value = str(aggregated_value if aggregated_value is not None else '')
self.write(row, column, aggregated_value, self.header_bold_style)
return row + 1, 0
-12
View File
@@ -317,18 +317,6 @@ class ProductTemplate(models.Model):
return combination_info
def _create_first_product_variant(self, log_warning=False):
"""Create if necessary and possible and return the first product
variant for this template.
:param log_warning: whether a warning should be logged on fail
:type log_warning: bool
:return: the first product variant or none
:rtype: recordset of `product.product`
"""
return self._create_product_variant(self._get_first_possible_combination(), log_warning)
def _get_image_holder(self):
"""Returns the holder of the image to use as default representation.
If the product template has an image it is the product template,