Pricing cron
This commit is contained in:
@@ -18,6 +18,9 @@ class Cron(metaclass=PoolMeta):
|
|||||||
cls.method.selection.append(
|
cls.method.selection.append(
|
||||||
('valuation.valuation|update_daily_snapshot',
|
('valuation.valuation|update_daily_snapshot',
|
||||||
"Update Valuation Snapshot"))
|
"Update Valuation Snapshot"))
|
||||||
|
cls.method.selection.append(
|
||||||
|
('pricing.pricing|update_daily_pricing',
|
||||||
|
"Update Pricing"))
|
||||||
|
|
||||||
class PriceCron(ModelSQL, ModelView):
|
class PriceCron(ModelSQL, ModelView):
|
||||||
"Price Cron"
|
"Price Cron"
|
||||||
|
|||||||
@@ -47,5 +47,11 @@
|
|||||||
<field name="interval_number" eval="1"/>
|
<field name="interval_number" eval="1"/>
|
||||||
<field name="interval_type">days</field>
|
<field name="interval_type">days</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.cron" id="pricing_daily_update_cron">
|
||||||
|
<field name="method">pricing.pricing|update_daily_pricing</field>
|
||||||
|
<field name="interval_number" eval="1"/>
|
||||||
|
<field name="interval_type">days</field>
|
||||||
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|||||||
@@ -1270,20 +1270,39 @@ class Pricing(ModelSQL,ModelView):
|
|||||||
"Pricing component must belong to the related line.")
|
"Pricing component must belong to the related line.")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _sync_eod_price(cls, records):
|
def _sync_eod_price(cls, records):
|
||||||
if not records:
|
if not records:
|
||||||
return
|
return
|
||||||
with Transaction().set_context(skip_pricing_eod_sync=True):
|
with Transaction().set_context(skip_pricing_eod_sync=True):
|
||||||
for record in records:
|
for record in records:
|
||||||
eod_price = record.compute_eod_price()
|
eod_price = record.compute_eod_price()
|
||||||
if Decimal(str(record.eod_price or 0)) == Decimal(str(eod_price or 0)):
|
if Decimal(str(record.eod_price or 0)) == Decimal(str(eod_price or 0)):
|
||||||
continue
|
continue
|
||||||
super(Pricing, cls).write([record], {
|
super(Pricing, cls).write([record], {
|
||||||
'eod_price': eod_price,
|
'eod_price': eod_price,
|
||||||
})
|
})
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _is_manual_pricing_record(cls, record):
|
def update_daily_pricing(cls):
|
||||||
|
PurchaseLine = Pool().get('purchase.line')
|
||||||
|
SaleLine = Pool().get('sale.line')
|
||||||
|
|
||||||
|
purchase_lines = PurchaseLine.search([])
|
||||||
|
sale_lines = SaleLine.search([])
|
||||||
|
|
||||||
|
for line in purchase_lines:
|
||||||
|
line.check_pricing()
|
||||||
|
|
||||||
|
for sale_line in sale_lines:
|
||||||
|
sale_line.check_pricing()
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"Updated pricing for %s purchase line(s) and %s sale line(s)",
|
||||||
|
len(purchase_lines),
|
||||||
|
len(sale_lines))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _is_manual_pricing_record(cls, record):
|
||||||
component = getattr(record, 'price_component', None)
|
component = getattr(record, 'price_component', None)
|
||||||
if component is None:
|
if component is None:
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -1260,6 +1260,31 @@ class PurchaseTradeTestCase(ModuleTestCase):
|
|||||||
self.assertEqual(generate.call_count, 2)
|
self.assertEqual(generate.call_count, 2)
|
||||||
generate_from_sale_line.assert_called_once_with(unmatched_sale_line)
|
generate_from_sale_line.assert_called_once_with(unmatched_sale_line)
|
||||||
|
|
||||||
|
def test_update_daily_pricing_checks_all_purchase_and_sale_lines(self):
|
||||||
|
'daily pricing cron refreshes purchase and sale pricing lines'
|
||||||
|
Pricing = Pool().get('pricing.pricing')
|
||||||
|
PurchaseLine = Mock()
|
||||||
|
SaleLine = Mock()
|
||||||
|
purchase_lines = [Mock(id=1), Mock(id=2)]
|
||||||
|
sale_lines = [Mock(id=3), Mock(id=4)]
|
||||||
|
PurchaseLine.search.return_value = purchase_lines
|
||||||
|
SaleLine.search.return_value = sale_lines
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
'trytond.modules.purchase_trade.pricing.Pool'
|
||||||
|
) as PoolMock:
|
||||||
|
PoolMock.return_value.get.side_effect = lambda name: {
|
||||||
|
'purchase.line': PurchaseLine,
|
||||||
|
'sale.line': SaleLine,
|
||||||
|
}[name]
|
||||||
|
|
||||||
|
Pricing.update_daily_pricing()
|
||||||
|
|
||||||
|
PurchaseLine.search.assert_called_once_with([])
|
||||||
|
SaleLine.search.assert_called_once_with([])
|
||||||
|
for line in purchase_lines + sale_lines:
|
||||||
|
line.check_pricing.assert_called_once_with()
|
||||||
|
|
||||||
def test_create_pnl_fee_from_line_accepts_missing_rate_amount(self):
|
def test_create_pnl_fee_from_line_accepts_missing_rate_amount(self):
|
||||||
'purchase fee valuation treats an uncomputed rate amount as zero'
|
'purchase fee valuation treats an uncomputed rate amount as zero'
|
||||||
Valuation = Pool().get('valuation.valuation')
|
Valuation = Pool().get('valuation.valuation')
|
||||||
|
|||||||
Reference in New Issue
Block a user