pricing manuel

This commit is contained in:
2026-04-09 22:38:48 +02:00
parent 0def187750
commit 472806ef06
2 changed files with 94 additions and 1 deletions

View File

@@ -413,19 +413,22 @@ class Pricing(ModelSQL,ModelView):
@classmethod @classmethod
def create(cls, vlist): def create(cls, vlist):
records = super(Pricing, cls).create(vlist) records = super(Pricing, cls).create(vlist)
cls._sync_manual_last(records)
cls._sync_eod_price(records) cls._sync_eod_price(records)
return records return records
@classmethod @classmethod
def write(cls, *args): def write(cls, *args):
super(Pricing, cls).write(*args) super(Pricing, cls).write(*args)
if Transaction().context.get('skip_pricing_eod_sync'): if (Transaction().context.get('skip_pricing_eod_sync')
or Transaction().context.get('skip_pricing_last_sync')):
return return
records = [] records = []
actions = iter(args) actions = iter(args)
for record_set, values in zip(actions, actions): for record_set, values in zip(actions, actions):
if values: if values:
records.extend(record_set) records.extend(record_set)
cls._sync_manual_last(records)
cls._sync_eod_price(records) cls._sync_eod_price(records)
@classmethod @classmethod
@@ -441,6 +444,64 @@ class Pricing(ModelSQL,ModelView):
'eod_price': eod_price, 'eod_price': eod_price,
}) })
@classmethod
def _get_manual_last_group_domain(cls, record):
component = getattr(record, 'price_component', None)
if getattr(record, 'sale_line', None):
domain = [
('sale_line', '=', record.sale_line.id),
]
domain.append((
'price_component',
'=',
component.id if getattr(component, 'id', None) else None,
))
return domain
if getattr(record, 'line', None):
domain = [
('line', '=', record.line.id),
]
domain.append((
'price_component',
'=',
component.id if getattr(component, 'id', None) else None,
))
return domain
return None
@classmethod
def _sync_manual_last(cls, records):
if not records:
return
domains = []
seen = set()
for record in records:
domain = cls._get_manual_last_group_domain(record)
if not domain:
continue
key = tuple(domain)
if key in seen:
continue
seen.add(key)
domains.append(domain)
if not domains:
return
with Transaction().set_context(
skip_pricing_last_sync=True,
skip_pricing_eod_sync=True):
for domain in domains:
pricings = cls.search(
domain,
order=[('pricing_date', 'ASC'), ('id', 'ASC')])
if not pricings:
continue
last_pricing = pricings[-1]
for pricing in pricings[:-1]:
if pricing.last:
super(Pricing, cls).write([pricing], {'last': False})
if not last_pricing.last:
super(Pricing, cls).write([last_pricing], {'last': True})
def get_fixed_price(self): def get_fixed_price(self):
price = Decimal(0) price = Decimal(0)
Pricing = Pool().get('pricing.pricing') Pricing = Pool().get('pricing.pricing')

View File

@@ -290,6 +290,38 @@ class PurchaseTradeTestCase(ModuleTestCase):
self.assertEqual( self.assertEqual(
purchase_pricing.get_eod_price_purchase(), Decimal('106.0000')) purchase_pricing.get_eod_price_purchase(), Decimal('106.0000'))
def test_pricing_sync_manual_last_uses_greatest_date_per_component_group(self):
'pricing rows keep one last by line/component, chosen by greatest pricing date'
Pricing = Pool().get('pricing.pricing')
sale_line = Mock(id=10)
component = Mock(id=33)
first = Mock(
id=1,
price_component=component,
sale_line=sale_line,
line=None,
pricing_date=datetime.date(2026, 4, 10),
last=True,
)
second = Mock(
id=2,
price_component=component,
sale_line=sale_line,
line=None,
pricing_date=datetime.date(2026, 4, 9),
last=False,
)
with patch.object(Pricing, 'search', return_value=[second, first]), patch(
'trytond.modules.purchase_trade.pricing.super') as super_mock:
Pricing._sync_manual_last([first, second])
self.assertEqual(super_mock.return_value.write.call_args_list[0].args[0], [second])
self.assertEqual(super_mock.return_value.write.call_args_list[0].args[1], {'last': False})
self.assertEqual(super_mock.return_value.write.call_args_list[1].args[0], [first])
self.assertEqual(super_mock.return_value.write.call_args_list[1].args[1], {'last': True})
def test_sale_and_purchase_trader_operator_domains_use_explicit_categories(self): def test_sale_and_purchase_trader_operator_domains_use_explicit_categories(self):
'sale and purchase trader/operator fields are filtered by TRADER/OPERATOR categories' 'sale and purchase trader/operator fields are filtered by TRADER/OPERATOR categories'
Sale = Pool().get('sale.sale') Sale = Pool().get('sale.sale')