diff --git a/modules/purchase_trade/pricing.py b/modules/purchase_trade/pricing.py index 4737b13..7393827 100755 --- a/modules/purchase_trade/pricing.py +++ b/modules/purchase_trade/pricing.py @@ -2,7 +2,7 @@ # this repository contains the full copyright notices and license terms. from trytond.model import fields from trytond.pool import Pool, PoolMeta -from trytond.pyson import Bool, Eval, Id, If +from trytond.pyson import Bool, Eval, Id from trytond.model import (ModelSQL, ModelView) from trytond.exceptions import UserError from trytond.tools import is_full_text, lstrip_wildcard @@ -333,12 +333,11 @@ class Pricing(ModelSQL,ModelView): pricing_date = fields.Date("Date") price_component = fields.Many2One( 'pricing.component', "Component", - domain=[If(Bool(Eval('line')), - ('line', '=', Eval('line')), - If(Bool(Eval('sale_line')), - ('sale_line', '=', Eval('sale_line')), - ('id', '=', -1)))], - depends=['line', 'sale_line'])#, ondelete='CASCADE') + domain=[('id', 'in', Eval('available_components', []))], + depends=['available_components'])#, ondelete='CASCADE') + available_components = fields.Function( + fields.One2Many('pricing.component', '', "Available Components"), + 'on_change_with_available_components') quantity = fields.Numeric("Qt",digits='unit') settl_price = fields.Numeric("Settl. price",digits='unit') fixed_qt = fields.Numeric("Fixed qt",digits='unit', readonly=True) @@ -368,14 +367,25 @@ class Pricing(ModelSQL,ModelView): def default_quantity(cls): return Decimal(0) - @classmethod - def default_settl_price(cls): - return Decimal(0) - + @classmethod + def default_settl_price(cls): + return Decimal(0) + @classmethod def default_eod_price(cls): return Decimal(0) + @fields.depends('line', 'sale_line') + def on_change_with_available_components(self, name=None): + Component = Pool().get('pricing.component') + line = getattr(self, 'line', None) + if line: + return Component.search([('line', '=', line)]) + sale_line = getattr(self, 'sale_line', None) + if sale_line: + return Component.search([('sale_line', '=', sale_line)]) + return [] + @staticmethod def _weighted_average_price(fixed_qt, fixed_price, unfixed_qt, unfixed_price): fixed_qt = Decimal(str(fixed_qt or 0)) diff --git a/modules/purchase_trade/purchase.py b/modules/purchase_trade/purchase.py index a36075d..ab15052 100755 --- a/modules/purchase_trade/purchase.py +++ b/modules/purchase_trade/purchase.py @@ -1101,6 +1101,22 @@ class Line(metaclass=PoolMeta): and bool(line.to_del) and line.from_del > line.to_del) + @classmethod + def _check_delivery_period_values(cls, lines, values=None): + values = values or {} + for line in lines: + from_del = values.get('from_del', getattr(line, 'from_del', None)) + to_del = values.get('to_del', getattr(line, 'to_del', None)) + if from_del and to_del and from_del > to_del: + raise UserError( + "Delivery period From date must be before To date.") + + @classmethod + def create(cls, vlist): + for values in vlist: + cls._check_delivery_period_values([cls()], values) + return super().create(vlist) + def _check_delivery_period(self): if self._has_invalid_delivery_period(self): raise UserError( @@ -1475,13 +1491,15 @@ class Line(metaclass=PoolMeta): # Si delta négatif alors on decrease si c'est possible le lot_qt non shippé non matché et s'il n'y en a pas on envoie un # message d'erreur 'Please unlink or unmatch lot' Lot = Pool().get('lot.lot') - LotQt = Pool().get('lot.qt') - old_values = {} - - for records, values in zip(args[::2], args[1::2]): - if 'quantity_theorical' in values: - for record in records: - old_values[record.id] = record.quantity_theorical + LotQt = Pool().get('lot.qt') + old_values = {} + + for records, values in zip(args[::2], args[1::2]): + if {'from_del', 'to_del'} & set(values): + cls._check_delivery_period_values(records, values) + if 'quantity_theorical' in values: + for record in records: + old_values[record.id] = record.quantity_theorical super().write(*args) diff --git a/modules/purchase_trade/sale.py b/modules/purchase_trade/sale.py index 5226ff2..ab65843 100755 --- a/modules/purchase_trade/sale.py +++ b/modules/purchase_trade/sale.py @@ -1084,6 +1084,22 @@ class SaleLine(metaclass=PoolMeta): and bool(line.to_del) and line.from_del > line.to_del) + @classmethod + def _check_delivery_period_values(cls, lines, values=None): + values = values or {} + for line in lines: + from_del = values.get('from_del', getattr(line, 'from_del', None)) + to_del = values.get('to_del', getattr(line, 'to_del', None)) + if from_del and to_del and from_del > to_del: + raise UserError( + "Delivery period From date must be before To date.") + + @classmethod + def create(cls, vlist): + for values in vlist: + cls._check_delivery_period_values([cls()], values) + return super().create(vlist) + def _check_delivery_period(self): if self._has_invalid_delivery_period(self): raise UserError( @@ -1593,6 +1609,8 @@ class SaleLine(metaclass=PoolMeta): old_values = {} for records, values in zip(args[::2], args[1::2]): + if {'from_del', 'to_del'} & set(values): + cls._check_delivery_period_values(records, values) if 'quantity_theorical' in values: for record in records: old_values[record.id] = record.quantity_theorical diff --git a/modules/purchase_trade/tests/test_module.py b/modules/purchase_trade/tests/test_module.py index 3443b35..d21542d 100644 --- a/modules/purchase_trade/tests/test_module.py +++ b/modules/purchase_trade/tests/test_module.py @@ -6,7 +6,7 @@ from decimal import Decimal from unittest.mock import Mock, patch from trytond.pool import Pool -from trytond.pyson import Bool, Eval, If +from trytond.pyson import Eval from trytond.tests.test_tryton import ModuleTestCase, with_transaction from trytond.exceptions import UserError from trytond.modules.purchase_trade import valuation as valuation_module @@ -528,11 +528,9 @@ class PurchaseTradeTestCase(ModuleTestCase): 'pricing component choices are limited to the purchase or sale line' Pricing = Pool().get('pricing.pricing') - self.assertEqual(Pricing.price_component.domain, [If(Bool(Eval('line')), - ('line', '=', Eval('line')), - If(Bool(Eval('sale_line')), - ('sale_line', '=', Eval('sale_line')), - ('id', '=', -1)))]) + self.assertEqual(Pricing.price_component.domain, [ + ('id', 'in', Eval('available_components', [])), + ]) def test_pricing_component_must_belong_to_pricing_owner(self): 'pricing rows reject components from another purchase or sale line' @@ -589,6 +587,14 @@ class PurchaseTradeTestCase(ModuleTestCase): purchase_line.on_change_from_del() with self.assertRaises(UserError): sale_line.on_change_to_del() + with self.assertRaises(UserError): + PurchaseLine._check_delivery_period_values([valid], { + 'from_del': invalid.from_del, + }) + with self.assertRaises(UserError): + SaleLine._check_delivery_period_values([valid], { + 'to_del': datetime.date(2026, 3, 31), + }) def test_pricing_eod_uses_weighted_average_for_manual_rows(self): 'manual pricing eod uses the weighted average of fixed and unfixed legs' diff --git a/modules/purchase_trade/view/pricing_form.xml b/modules/purchase_trade/view/pricing_form.xml index 50f6095..d22a528 100755 --- a/modules/purchase_trade/view/pricing_form.xml +++ b/modules/purchase_trade/view/pricing_form.xml @@ -1,6 +1,7 @@