This commit is contained in:
2026-07-16 15:09:54 +02:00
parent cda8b4067b
commit a0bd6f0e28
5 changed files with 109 additions and 9 deletions

View File

@@ -1074,6 +1074,17 @@ class CoffeeLabAnalysis(Workflow, ModelSQL, ModelView):
class CoffeeLineMixin:
_coffee_attribute_name_fields = [
('coffee_origin', None),
('coffee_type', dict(COFFEE_TYPES)),
('coffee_process', dict(COFFEE_PROCESS_TYPES)),
('coffee_variety', None),
('coffee_crop_year', None),
('coffee_screen_size', None),
('coffee_moisture_max', None),
('coffee_defect_max', None),
('coffee_cup_score_min', None),
]
_coffee_view_fields = {
'coffee_quality_status',
'coffee_origin',
@@ -1131,6 +1142,18 @@ class CoffeeLineMixin:
def on_change_with_active_coffee_compatibility(self, name=None):
return self.get_active_coffee_compatibility(name)
def _coffee_attributes_name(self):
values = []
for field_name, selection in self._coffee_attribute_name_fields:
value = getattr(self, field_name, None)
if value is None or value == '':
continue
if selection:
value = selection.get(value, value)
values.append(str(value))
if values:
return ' | '.join(values)
@classmethod
def fields_view_get(cls, view_id=None, view_type='form', level=None):
result = super().fields_view_get(

View File

@@ -2448,14 +2448,22 @@ class Line(metaclass=PoolMeta):
@fields.depends('product')
def on_change_with_attribute_set(self, name=None):
if self.product and self.product.template and self.product.template.attribute_set:
return self.product.template.attribute_set.id
@fields.depends('product', 'attributes')
def on_change_with_attributes_name(self, name=None):
if not self.product or not self.product.attribute_set or not self.attributes:
return
if self.product and self.product.template and self.product.template.attribute_set:
return self.product.template.attribute_set.id
@fields.depends(
'product', 'attributes',
'coffee_origin', 'coffee_type', 'coffee_process', 'coffee_variety',
'coffee_crop_year', 'coffee_screen_size', 'coffee_moisture_max',
'coffee_defect_max', 'coffee_cup_score_min')
def on_change_with_attributes_name(self, name=None):
coffee_attributes_name = getattr(
self, '_coffee_attributes_name', lambda: None)()
if coffee_attributes_name:
return coffee_attributes_name
if not self.product or not self.product.attribute_set or not self.attributes:
return
def key(attribute):
return getattr(attribute, 'sequence', attribute.name)

View File

@@ -2264,8 +2264,16 @@ class SaleLine(metaclass=PoolMeta):
if self.product and self.product.template and self.product.template.attribute_set:
return self.product.template.attribute_set.id
@fields.depends('product', 'attributes')
@fields.depends(
'product', 'attributes',
'coffee_origin', 'coffee_type', 'coffee_process', 'coffee_variety',
'coffee_crop_year', 'coffee_screen_size', 'coffee_moisture_max',
'coffee_defect_max', 'coffee_cup_score_min')
def on_change_with_attributes_name(self, name=None):
coffee_attributes_name = getattr(
self, '_coffee_attributes_name', lambda: None)()
if coffee_attributes_name:
return coffee_attributes_name
if not self.product or not self.product.attribute_set or not self.attributes:
return

View File

@@ -82,6 +82,62 @@ class PurchaseTradeTestCase(ModuleTestCase):
self.assertEqual([line.sample.reference for line in ordered], ['A', 'R'])
def test_coffee_line_attributes_name_uses_quality_fields(self):
'coffee line attribute name is built from coffee quality fields'
line = SimpleNamespace(
coffee_origin='Brazil',
coffee_type='arabica',
coffee_process='natural',
coffee_variety='Bourbon',
coffee_crop_year='26/27',
coffee_screen_size='17/18',
coffee_moisture_max=Decimal('11.50'),
coffee_defect_max=12,
coffee_cup_score_min=Decimal('82.00'))
self.assertEqual(
coffee_module.CoffeeLineMixin._coffee_attributes_name(line),
'Brazil | Arabica | Natural | Bourbon | 26/27 | 17/18 | '
'11.50 | 12 | 82.00')
def test_coffee_line_attributes_name_ignores_empty_quality_fields(self):
'empty coffee quality fields keep the standard product attributes name'
line = SimpleNamespace(
coffee_origin='',
coffee_type=None,
coffee_process=None,
coffee_variety=None,
coffee_crop_year=None,
coffee_screen_size=None,
coffee_moisture_max=None,
coffee_defect_max=None,
coffee_cup_score_min=None)
self.assertIsNone(
coffee_module.CoffeeLineMixin._coffee_attributes_name(line))
def test_purchase_line_attributes_name_prefers_coffee_quality(self):
'purchase line attributes name uses coffee quality when available'
line = SimpleNamespace(
_coffee_attributes_name=lambda: 'Brazil | Arabica',
product=None,
attributes=None)
self.assertEqual(
purchase_module.Line.on_change_with_attributes_name(line),
'Brazil | Arabica')
def test_sale_line_attributes_name_prefers_coffee_quality(self):
'sale line attributes name uses coffee quality when available'
line = SimpleNamespace(
_coffee_attributes_name=lambda: 'Brazil | Arabica',
product=None,
attributes=None)
self.assertEqual(
sale_module.SaleLine.on_change_with_attributes_name(line),
'Brazil | Arabica')
def test_coffee_lab_analysis_compliance_uses_line_targets(self):
'coffee lab analysis compliance checks sample line targets'
line = SimpleNamespace(
@@ -2111,10 +2167,12 @@ class PurchaseTradeTestCase(ModuleTestCase):
self.assertEqual(values[0]['amount'], Decimal('-200.00'))
self.assertEqual(values[0]['base_amount'], Decimal('-200'))
self.assertEqual(values[0]['date'], today)
self.assertIsNone(values[0]['mtm_price'])
self.assertIsNone(values[0]['mtm'])
self.assertEqual(values[1]['amount'], Decimal('200.00'))
self.assertEqual(values[1]['base_amount'], Decimal('200'))
self.assertEqual(values[1]['date'], today)
self.assertIsNone(values[1]['mtm_price'])
self.assertIsNone(values[1]['mtm'])
@@ -2154,6 +2212,7 @@ class PurchaseTradeTestCase(ModuleTestCase):
values = Valuation.create_pnl_der_from_sale_line(sale_line)
self.assertEqual(values[0]['price'], Decimal('100.0000'))
self.assertEqual(values[0]['date'], today)
self.assertEqual(values[0]['amount'], Decimal('200.00'))
self.assertEqual(values[0]['base_amount'], Decimal('200'))
self.assertIsNone(values[0]['mtm_price'])

View File

@@ -1597,6 +1597,7 @@ class ValuationBase(ModelSQL):
@classmethod
def create_pnl_der_from_line(cls, line):
der_lines = []
Date = Pool().get('ir.date')
for d in line.derivatives or []:
currency = line.purchase.currency
@@ -1631,6 +1632,7 @@ class ValuationBase(ModelSQL):
@classmethod
def create_pnl_der_from_sale_line(cls, sale_line):
der_lines = []
Date = Pool().get('ir.date')
for d in sale_line.derivatives or []:
currency = sale_line.sale.currency