bug Th qt
This commit is contained in:
@@ -1631,19 +1631,20 @@ class Line(metaclass=PoolMeta):
|
|||||||
|
|
||||||
if self.price_components:
|
if self.price_components:
|
||||||
for pc in self.price_components:
|
for pc in self.price_components:
|
||||||
if not pc.auto:
|
if not pc.auto:
|
||||||
Pricing = Pool().get('pricing.pricing')
|
Pricing = Pool().get('pricing.pricing')
|
||||||
pricings = Pricing.search(['price_component','=',pc.id],order=[('pricing_date', 'ASC')])
|
pricings = Pricing.search(['price_component','=',pc.id],order=[('pricing_date', 'ASC')])
|
||||||
if pricings:
|
if pricings:
|
||||||
cumul_qt = Decimal(0)
|
cumul_qt = Decimal(0)
|
||||||
index = 0
|
base_quantity = self._get_pricing_base_quantity()
|
||||||
for pr in pricings:
|
index = 0
|
||||||
cumul_qt += pr.quantity
|
for pr in pricings:
|
||||||
pr.fixed_qt = cumul_qt
|
cumul_qt += pr.quantity
|
||||||
pr.fixed_qt_price = pr.get_fixed_price()
|
pr.fixed_qt = cumul_qt
|
||||||
pr.unfixed_qt = Decimal(pr.line.quantity_theorical) - pr.fixed_qt
|
pr.fixed_qt_price = pr.get_fixed_price()
|
||||||
pr.unfixed_qt_price = pr.fixed_qt_price
|
pr.unfixed_qt = base_quantity - pr.fixed_qt
|
||||||
pr.eod_price = pr.get_eod_price_purchase()
|
pr.unfixed_qt_price = pr.fixed_qt_price
|
||||||
|
pr.eod_price = pr.get_eod_price_purchase()
|
||||||
if index == len(pricings) - 1:
|
if index == len(pricings) - 1:
|
||||||
pr.last = True
|
pr.last = True
|
||||||
index += 1
|
index += 1
|
||||||
@@ -1678,9 +1679,9 @@ class Line(metaclass=PoolMeta):
|
|||||||
i += 1
|
i += 1
|
||||||
return lprice
|
return lprice
|
||||||
|
|
||||||
def getnearprice(self,pl,d,t,max_date=None):
|
def getnearprice(self,pl,d,t,max_date=None):
|
||||||
if pl:
|
if pl:
|
||||||
pl_sorted = sorted(pl, key=lambda x: x['date'])
|
pl_sorted = sorted(pl, key=lambda x: x['date'])
|
||||||
pminus = pl_sorted[0]
|
pminus = pl_sorted[0]
|
||||||
if not max_date:
|
if not max_date:
|
||||||
max_date = d.date()
|
max_date = d.date()
|
||||||
@@ -1695,17 +1696,24 @@ class Line(metaclass=PoolMeta):
|
|||||||
return pminus[t]
|
return pminus[t]
|
||||||
else:
|
else:
|
||||||
return Decimal(0)
|
return Decimal(0)
|
||||||
pminus = p
|
pminus = p
|
||||||
return pl_sorted[len(pl)-1][t]
|
return pl_sorted[len(pl)-1][t]
|
||||||
return Decimal(0)
|
return Decimal(0)
|
||||||
|
|
||||||
def generate_pricing(self,pc,dl,pl):
|
def _get_pricing_base_quantity(self):
|
||||||
Pricing = Pool().get('pricing.pricing')
|
quantity = self.quantity_theorical
|
||||||
pricing = Pricing.search(['price_component','=',pc.id])
|
if quantity is None:
|
||||||
if pricing:
|
quantity = self.quantity
|
||||||
Pricing.delete(pricing)
|
return Decimal(str(quantity or 0))
|
||||||
cumul_qt = 0
|
|
||||||
index = 0
|
def generate_pricing(self,pc,dl,pl):
|
||||||
|
Pricing = Pool().get('pricing.pricing')
|
||||||
|
pricing = Pricing.search(['price_component','=',pc.id])
|
||||||
|
if pricing:
|
||||||
|
Pricing.delete(pricing)
|
||||||
|
base_quantity = self._get_pricing_base_quantity()
|
||||||
|
cumul_qt = 0
|
||||||
|
index = 0
|
||||||
dl_sorted = sorted(dl)
|
dl_sorted = sorted(dl)
|
||||||
for d in dl_sorted:
|
for d in dl_sorted:
|
||||||
if pc.pricing_date and d.date() > pc.pricing_date:
|
if pc.pricing_date and d.date() > pc.pricing_date:
|
||||||
@@ -1720,16 +1728,16 @@ class Line(metaclass=PoolMeta):
|
|||||||
if price > 0:
|
if price > 0:
|
||||||
cumul_qt += pc.quota
|
cumul_qt += pc.quota
|
||||||
p.fixed_qt = round(Decimal(cumul_qt),5)
|
p.fixed_qt = round(Decimal(cumul_qt),5)
|
||||||
p.fixed_qt_price = round(Decimal(self.getnearprice(pl,d,'avg')),4)
|
p.fixed_qt_price = round(Decimal(self.getnearprice(pl,d,'avg')),4)
|
||||||
#p.fixed_qt_price = p.get_fixed_price()
|
#p.fixed_qt_price = p.get_fixed_price()
|
||||||
if p.fixed_qt_price == 0:
|
if p.fixed_qt_price == 0:
|
||||||
p.fixed_qt_price = round(Decimal(self.getnearprice(pl,d,'avg_minus_1')),4)
|
p.fixed_qt_price = round(Decimal(self.getnearprice(pl,d,'avg_minus_1')),4)
|
||||||
p.unfixed_qt = round(Decimal(self.quantity_theorical) - Decimal(cumul_qt),5)
|
p.unfixed_qt = round(base_quantity - Decimal(cumul_qt),5)
|
||||||
if p.unfixed_qt < 0.001:
|
if p.unfixed_qt < 0.001:
|
||||||
p.unfixed_qt = Decimal(0)
|
p.unfixed_qt = Decimal(0)
|
||||||
p.fixed_qt = Decimal(self.quantity_theorical)
|
p.fixed_qt = base_quantity
|
||||||
if price > 0:
|
if price > 0:
|
||||||
p.unfixed_qt_price = price
|
p.unfixed_qt_price = price
|
||||||
else:
|
else:
|
||||||
pr = Decimal(pc.price_index.get_price(p.pricing_date,self.unit,self.purchase.currency,True))
|
pr = Decimal(pc.price_index.get_price(p.pricing_date,self.unit,self.purchase.currency,True))
|
||||||
pr = round(pr,4)
|
pr = round(pr,4)
|
||||||
|
|||||||
@@ -1245,19 +1245,20 @@ class SaleLine(metaclass=PoolMeta):
|
|||||||
def check_pricing(self):
|
def check_pricing(self):
|
||||||
if self.price_components:
|
if self.price_components:
|
||||||
for pc in self.price_components:
|
for pc in self.price_components:
|
||||||
if not pc.auto:
|
if not pc.auto:
|
||||||
Pricing = Pool().get('pricing.pricing')
|
Pricing = Pool().get('pricing.pricing')
|
||||||
pricings = Pricing.search(['price_component','=',pc.id],order=[('pricing_date', 'ASC')])
|
pricings = Pricing.search(['price_component','=',pc.id],order=[('pricing_date', 'ASC')])
|
||||||
if pricings:
|
if pricings:
|
||||||
cumul_qt = Decimal(0)
|
cumul_qt = Decimal(0)
|
||||||
index = 0
|
base_quantity = self._get_pricing_base_quantity()
|
||||||
for pr in pricings:
|
index = 0
|
||||||
cumul_qt += pr.quantity
|
for pr in pricings:
|
||||||
pr.fixed_qt = cumul_qt
|
cumul_qt += pr.quantity
|
||||||
pr.fixed_qt_price = pr.get_fixed_price()
|
pr.fixed_qt = cumul_qt
|
||||||
pr.unfixed_qt = Decimal(pr.sale_line.quantity_theorical) - pr.fixed_qt
|
pr.fixed_qt_price = pr.get_fixed_price()
|
||||||
pr.unfixed_qt_price = pr.fixed_qt_price
|
pr.unfixed_qt = base_quantity - pr.fixed_qt
|
||||||
pr.eod_price = pr.get_eod_price_sale()
|
pr.unfixed_qt_price = pr.fixed_qt_price
|
||||||
|
pr.eod_price = pr.get_eod_price_sale()
|
||||||
if index == len(pricings) - 1:
|
if index == len(pricings) - 1:
|
||||||
pr.last = True
|
pr.last = True
|
||||||
index += 1
|
index += 1
|
||||||
@@ -1292,9 +1293,9 @@ class SaleLine(metaclass=PoolMeta):
|
|||||||
i += 1
|
i += 1
|
||||||
return lprice
|
return lprice
|
||||||
|
|
||||||
def getnearprice(self,pl,d,t,max_date=None):
|
def getnearprice(self,pl,d,t,max_date=None):
|
||||||
if pl:
|
if pl:
|
||||||
pl_sorted = sorted(pl, key=lambda x: x['date'])
|
pl_sorted = sorted(pl, key=lambda x: x['date'])
|
||||||
pminus = pl_sorted[0]
|
pminus = pl_sorted[0]
|
||||||
if not max_date:
|
if not max_date:
|
||||||
max_date = d.date()
|
max_date = d.date()
|
||||||
@@ -1309,17 +1310,24 @@ class SaleLine(metaclass=PoolMeta):
|
|||||||
return pminus[t]
|
return pminus[t]
|
||||||
else:
|
else:
|
||||||
return Decimal(0)
|
return Decimal(0)
|
||||||
pminus = p
|
pminus = p
|
||||||
return pl_sorted[len(pl)-1][t]
|
return pl_sorted[len(pl)-1][t]
|
||||||
return Decimal(0)
|
return Decimal(0)
|
||||||
|
|
||||||
def generate_pricing(self,pc,dl,pl):
|
def _get_pricing_base_quantity(self):
|
||||||
Pricing = Pool().get('pricing.pricing')
|
quantity = self.quantity_theorical
|
||||||
pricing = Pricing.search(['price_component','=',pc.id])
|
if quantity is None:
|
||||||
if pricing:
|
quantity = self.quantity
|
||||||
Pricing.delete(pricing)
|
return Decimal(str(quantity or 0))
|
||||||
cumul_qt = 0
|
|
||||||
index = 0
|
def generate_pricing(self,pc,dl,pl):
|
||||||
|
Pricing = Pool().get('pricing.pricing')
|
||||||
|
pricing = Pricing.search(['price_component','=',pc.id])
|
||||||
|
if pricing:
|
||||||
|
Pricing.delete(pricing)
|
||||||
|
base_quantity = self._get_pricing_base_quantity()
|
||||||
|
cumul_qt = 0
|
||||||
|
index = 0
|
||||||
dl_sorted = sorted(dl)
|
dl_sorted = sorted(dl)
|
||||||
for d in dl_sorted:
|
for d in dl_sorted:
|
||||||
if pc.pricing_date and d.date() > pc.pricing_date:
|
if pc.pricing_date and d.date() > pc.pricing_date:
|
||||||
@@ -1336,17 +1344,17 @@ class SaleLine(metaclass=PoolMeta):
|
|||||||
if price > 0:
|
if price > 0:
|
||||||
cumul_qt += pc.quota_sale
|
cumul_qt += pc.quota_sale
|
||||||
p.fixed_qt = round(Decimal(cumul_qt),4)
|
p.fixed_qt = round(Decimal(cumul_qt),4)
|
||||||
p.fixed_qt_price = round(Decimal(self.getnearprice(pl,d,'avg',pc.pricing_date)),4)
|
p.fixed_qt_price = round(Decimal(self.getnearprice(pl,d,'avg',pc.pricing_date)),4)
|
||||||
#p.fixed_qt_price = p.get_fixed_price()
|
#p.fixed_qt_price = p.get_fixed_price()
|
||||||
if p.fixed_qt_price == 0:
|
if p.fixed_qt_price == 0:
|
||||||
p.fixed_qt_price = round(Decimal(self.getnearprice(pl,d,'avg_minus_1',pc.pricing_date)),4)
|
p.fixed_qt_price = round(Decimal(self.getnearprice(pl,d,'avg_minus_1',pc.pricing_date)),4)
|
||||||
p.unfixed_qt = round(Decimal(self.quantity_theorical) - Decimal(cumul_qt),4)
|
p.unfixed_qt = round(base_quantity - Decimal(cumul_qt),4)
|
||||||
if p.unfixed_qt < 0.001:
|
if p.unfixed_qt < 0.001:
|
||||||
p.unfixed_qt = Decimal(0)
|
p.unfixed_qt = Decimal(0)
|
||||||
p.fixed_qt = Decimal(self.quantity_theorical)
|
p.fixed_qt = base_quantity
|
||||||
if price > 0:
|
if price > 0:
|
||||||
logger.info("GENERATE_1:%s",price)
|
logger.info("GENERATE_1:%s",price)
|
||||||
p.unfixed_qt_price = price
|
p.unfixed_qt_price = price
|
||||||
else:
|
else:
|
||||||
pr = Decimal(pc.price_index.get_price(p.pricing_date,self.unit,self.sale.currency,True))
|
pr = Decimal(pc.price_index.get_price(p.pricing_date,self.unit,self.sale.currency,True))
|
||||||
pr = round(pr,4)
|
pr = round(pr,4)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||||
# this repository contains the full copyright notices and license terms.
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
|
import datetime
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from unittest.mock import Mock, patch
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
@@ -208,6 +209,43 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
|||||||
purchase_component.get_quota_purchase('quota'),
|
purchase_component.get_quota_purchase('quota'),
|
||||||
Decimal('15.00000'))
|
Decimal('15.00000'))
|
||||||
|
|
||||||
|
def test_sale_and_purchase_generate_pricing_use_quantity_fallback(self):
|
||||||
|
'pricing generation uses quantity when theoretical quantity is missing'
|
||||||
|
Sale = Pool().get('sale.sale')
|
||||||
|
Purchase = Pool().get('purchase.purchase')
|
||||||
|
|
||||||
|
sale = Sale()
|
||||||
|
sale.id = 1
|
||||||
|
sale.quantity = Decimal('10')
|
||||||
|
sale.quantity_theorical = None
|
||||||
|
sale.unit = Mock()
|
||||||
|
sale.sale = Mock(currency=Mock())
|
||||||
|
sale.getnearprice = Mock(return_value=Decimal('0'))
|
||||||
|
|
||||||
|
purchase = Purchase()
|
||||||
|
purchase.id = 1
|
||||||
|
purchase.quantity = Decimal('12')
|
||||||
|
purchase.quantity_theorical = None
|
||||||
|
purchase.unit = Mock()
|
||||||
|
purchase.purchase = Mock(currency=Mock())
|
||||||
|
purchase.getnearprice = Mock(return_value=Decimal('0'))
|
||||||
|
|
||||||
|
pricing_model = Mock()
|
||||||
|
pricing_model.search.return_value = []
|
||||||
|
pc_sale = Mock(id=1, quota_sale=Decimal('2'), pricing_date=None, price_index=Mock(get_price=Mock(return_value=Decimal('1'))))
|
||||||
|
pc_purchase = Mock(id=1, quota=Decimal('3'), pricing_date=None, price_index=Mock(get_price=Mock(return_value=Decimal('1'))))
|
||||||
|
|
||||||
|
with patch('trytond.modules.purchase_trade.sale.Pool') as SalePool, patch(
|
||||||
|
'trytond.modules.purchase_trade.purchase.Pool') as PurchasePool:
|
||||||
|
SalePool.return_value.get.return_value = pricing_model
|
||||||
|
PurchasePool.return_value.get.return_value = pricing_model
|
||||||
|
|
||||||
|
sale.generate_pricing(pc_sale, [datetime.datetime(2026, 4, 1)], [])
|
||||||
|
purchase.generate_pricing(pc_purchase, [datetime.datetime(2026, 4, 1)], [])
|
||||||
|
|
||||||
|
self.assertEqual(pricing_model.save.call_args_list[0].args[0][0].unfixed_qt, Decimal('10'))
|
||||||
|
self.assertEqual(pricing_model.save.call_args_list[1].args[0][0].unfixed_qt, Decimal('12'))
|
||||||
|
|
||||||
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')
|
||||||
|
|||||||
Reference in New Issue
Block a user