From 062b42f83fb0dfa46190d08e896a228ce98002be Mon Sep 17 00:00:00 2001 From: laurentbarontini Date: Tue, 28 Apr 2026 20:32:04 +0200 Subject: [PATCH] Bug From To --- modules/purchase_trade/purchase.py | 43 +++++++++++++++--- modules/purchase_trade/sale.py | 49 ++++++++++++++++----- modules/purchase_trade/tests/test_module.py | 25 +++++++++++ 3 files changed, 100 insertions(+), 17 deletions(-) diff --git a/modules/purchase_trade/purchase.py b/modules/purchase_trade/purchase.py index 078d404..ed3bce4 100755 --- a/modules/purchase_trade/purchase.py +++ b/modules/purchase_trade/purchase.py @@ -564,13 +564,42 @@ class Purchase(metaclass=PoolMeta): def on_change_with_viewer(self): return self.get_viewer() - @fields.depends('doc_template','required_documents') - def on_change_with_required_documents(self): - if self.doc_template: - return self.doc_template.type - - @classmethod - def copy(cls, purchases, default=None): + @fields.depends('doc_template','required_documents') + def on_change_with_required_documents(self): + if self.doc_template: + return self.doc_template.type + + @classmethod + def _check_lines_delivery_period_values(cls, values): + line_commands = values.get('lines') or [] + if not line_commands: + return + Line = Pool().get('purchase.line') + for command in line_commands: + action = command[0] + if action == 'create': + for line_values in command[1]: + Line._check_delivery_period_values([Line()], line_values) + elif action == 'write': + actions = iter(command[1:]) + for line_ids, line_values in zip(actions, actions): + lines = Line.browse(line_ids) + Line._check_delivery_period_values(lines, line_values) + elif action == 'add': + lines = Line.browse(command[1]) + Line._check_delivery_period_values(lines) + + @classmethod + def write(cls, *args): + actions = iter(args) + args = [] + for purchases, values in zip(actions, actions): + cls._check_lines_delivery_period_values(values) + args.extend((purchases, values)) + super().write(*args) + + @classmethod + def copy(cls, purchases, default=None): if default is None: default = {} else: diff --git a/modules/purchase_trade/sale.py b/modules/purchase_trade/sale.py index a82eb55..e42ba3a 100755 --- a/modules/purchase_trade/sale.py +++ b/modules/purchase_trade/sale.py @@ -221,8 +221,8 @@ class Lot(metaclass=PoolMeta): if self.sale_line: return self.sale_line.sale.id -class Sale(metaclass=PoolMeta): - __name__ = 'sale.sale' +class Sale(metaclass=PoolMeta): + __name__ = 'sale.sale' btb = fields.Many2One('back.to.back',"Back to back") bank_accounts = fields.Function( @@ -992,14 +992,43 @@ class Sale(metaclass=PoolMeta): def on_change_with_viewer(self): return self.get_viewer() - def getLots(self): - if self.lines: - if self.lines.lots: - return [l for l in self.lines.lots] - - @classmethod - def validate(cls, sales): - super(Sale, cls).validate(sales) + def getLots(self): + if self.lines: + if self.lines.lots: + return [l for l in self.lines.lots] + + @classmethod + def _check_lines_delivery_period_values(cls, values): + line_commands = values.get('lines') or [] + if not line_commands: + return + Line = Pool().get('sale.line') + for command in line_commands: + action = command[0] + if action == 'create': + for line_values in command[1]: + Line._check_delivery_period_values([Line()], line_values) + elif action == 'write': + actions = iter(command[1:]) + for line_ids, line_values in zip(actions, actions): + lines = Line.browse(line_ids) + Line._check_delivery_period_values(lines, line_values) + elif action == 'add': + lines = Line.browse(command[1]) + Line._check_delivery_period_values(lines) + + @classmethod + def write(cls, *args): + actions = iter(args) + args = [] + for sales, values in zip(actions, actions): + cls._check_lines_delivery_period_values(values) + args.extend((sales, values)) + super().write(*args) + + @classmethod + def validate(cls, sales): + super(Sale, cls).validate(sales) Line = Pool().get('sale.line') Date = Pool().get('ir.date') for sale in sales: diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py index c0233e4..7ca0d1d 100644 --- a/modules/purchase_trade/tests/test_module.py +++ b/modules/purchase_trade/tests/test_module.py @@ -604,6 +604,31 @@ class PurchaseTradeTestCase(ModuleTestCase): 'quantity': Decimal('1'), }) + def test_sale_and_purchase_parent_write_check_embedded_line_commands(self): + 'sale and purchase writes validate embedded one2many line commands' + Sale = Pool().get('sale.sale') + Purchase = Pool().get('purchase.purchase') + invalid = Mock( + from_del=datetime.date(2026, 4, 16), + to_del=datetime.date(2026, 4, 10), + ) + + with patch('trytond.modules.purchase_trade.sale.Pool') as SalePool: + SalePool.return_value.get.return_value = Mock( + browse=Mock(return_value=[invalid])) + with self.assertRaises(UserError): + Sale._check_lines_delivery_period_values({ + 'lines': [['write', [564], {'quantity': Decimal('1')}]], + }) + + with patch('trytond.modules.purchase_trade.purchase.Pool') as PurchasePool: + PurchasePool.return_value.get.return_value = Mock( + browse=Mock(return_value=[invalid])) + with self.assertRaises(UserError): + Purchase._check_lines_delivery_period_values({ + 'lines': [['add', [564]]], + }) + def test_pricing_eod_uses_weighted_average_for_manual_rows(self): 'manual pricing eod uses the weighted average of fixed and unfixed legs' Pricing = Pool().get('pricing.pricing')