Import Prices (All Sources)

This commit is contained in:
AzureAD\SylvainDUVERNAY
2026-07-14 16:13:21 +02:00
parent 808e75daa6
commit fab46dde2f
2 changed files with 178 additions and 29 deletions

View File

@@ -2,9 +2,11 @@
# this repository contains the full copyright notices and license terms.
import datetime
import zipfile
from pathlib import Path
from contextlib import nullcontext
from decimal import Decimal
from io import BytesIO
from types import SimpleNamespace
from unittest.mock import ANY, Mock, call, patch
from xml.etree import ElementTree
@@ -5190,6 +5192,57 @@ class PurchaseTradeTestCase(ModuleTestCase):
self.assertEqual(result[0]['mid_price'], '75.25')
self.assertEqual(result[0]['high_price'], '75.25')
def test_import_historical_prices_computes_mid_from_low_high(self):
'historical import computes mid price from low and high prices'
ImportPrices = Pool().get('purchase_trade.import_prices')
ns = {'s': 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'}
sheet = ElementTree.fromstring('''
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<sheetData>
<row r="1">
<c r="A1" t="inlineStr"><is><t>Price Index</t></is></c>
<c r="B1" t="inlineStr"><is><t>Price Date</t></is></c>
<c r="C1" t="inlineStr"><is><t>High Price</t></is></c>
<c r="D1" t="inlineStr"><is><t>Low Price</t></is></c>
<c r="E1" t="inlineStr"><is><t>Open Price</t></is></c>
<c r="F1" t="inlineStr"><is><t>Price Value</t></is></c>
</row>
<row r="2">
<c r="A2" t="inlineStr"><is><t>ARGUS-CFR Brasil</t></is></c>
<c r="B2"><v>46191</v></c>
<c r="C2"><v>482</v></c>
<c r="D2"><v>460</v></c>
<c r="E2"><v>470</v></c>
<c r="F2"><v>470</v></c>
</row>
</sheetData>
</worksheet>
''')
rows = sheet.findall('.//s:sheetData/s:row', ns)
result = ImportPrices._read_historical_price_rows(rows, [], ns)
values = ImportPrices._price_value_values(
Mock(id=1), result[0], datetime.date(2026, 6, 18))
self.assertNotIn('mid_price', result[0])
self.assertEqual(values['mid_price'], 471)
def test_import_forward_price_values_compute_mid_from_low_high(self):
'forward import value builder computes mid price from low and high'
ImportPrices = Pool().get('purchase_trade.import_prices')
values = ImportPrices._price_value_values(
Mock(id=1), {
'high_price': '482',
'low_price': '460',
'mid_price': '0',
'open_price': '470',
'price_value': '470',
},
datetime.date(2026, 6, 18))
self.assertEqual(values['mid_price'], 471)
@with_transaction()
def test_import_historical_all_sources_uses_mapping_table(self):
'all sources import maps source columns to standard price values'
@@ -5211,7 +5264,7 @@ description</t></is></c>
<row r="3">
<c r="A3"><v>46191</v></c>
<c r="B3"><v>470</v></c>
<c r="C3"><v>480</v></c>
<c r="C3"><v>482</v></c>
<c r="D3"><v>460</v></c>
</row>
</sheetData>
@@ -5261,10 +5314,75 @@ description</t></is></c>
self.assertEqual(result[0]['price_date'], '46191')
self.assertEqual(result[0]['mid_price'], '470')
self.assertEqual(result[0]['price_value'], '470')
self.assertEqual(result[0]['high_price'], '480')
self.assertEqual(result[0]['open_price'], '470')
self.assertEqual(result[0]['high_price'], '482')
self.assertEqual(result[0]['low_price'], '460')
self.assertEqual(result[0]['_source'], 'ARGUS')
self.assertEqual(result[0]['_price_desc'], 'Brazil CFR')
values = ImportPrices._price_value_values(
Mock(id=1), result[0], datetime.date(2026, 6, 18))
self.assertEqual(values['mid_price'], 470)
def test_import_xlsx_uses_selected_parser(self):
'price import selects parser from requested file structure'
ImportPrices = Pool().get('purchase_trade.import_prices')
workbook = BytesIO()
with zipfile.ZipFile(workbook, 'w') as archive:
archive.writestr('xl/workbook.xml', '''
<workbook
xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<sheets>
<sheet name="Prices" sheetId="1" r:id="rId1"/>
</sheets>
</workbook>
''')
archive.writestr('xl/_rels/workbook.xml.rels', '''
<Relationships
xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Target="worksheets/sheet1.xml"/>
</Relationships>
''')
archive.writestr('xl/worksheets/sheet1.xml', '''
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<sheetData>
<row r="1">
<c r="A1" t="inlineStr"><is><t>Price Index</t></is></c>
<c r="B1" t="inlineStr"><is><t>Price Date</t></is></c>
</row>
<row r="2">
<c r="A2" t="inlineStr"><is><t>ARGUS-CFR Brasil</t></is></c>
<c r="B2"><v>46191</v></c>
</row>
</sheetData>
</worksheet>
''')
data = workbook.getvalue()
with patch.object(
ImportPrices, '_read_historical_price_rows',
return_value=['historical']) as historical, \
patch.object(
ImportPrices, '_read_historical_all_sources_price_rows',
return_value=['all_sources']) as all_sources, \
patch.object(
ImportPrices, '_read_forward_price_rows',
return_value=['forward']) as forward:
self.assertEqual(
ImportPrices._read_xlsx(
data, file_structure='historical'),
['historical'])
self.assertEqual(
ImportPrices._read_xlsx(
data, file_structure='historical_all_sources'),
['all_sources'])
self.assertEqual(
ImportPrices._read_xlsx(data, file_structure='forward'),
['forward'])
self.assertEqual(historical.call_count, 1)
self.assertEqual(all_sources.call_count, 1)
self.assertEqual(forward.call_count, 1)
def test_import_historical_all_sources_requires_exact_tab_match(self):
'all sources import ignores similarly named source sheets'
@@ -5295,6 +5413,14 @@ description</t></is></c>
self.assertEqual(values['price_desc'], 'Brazil CFR')
self.assertEqual(values['price_area'], 8)
def test_import_price_date_accepts_dot_format(self):
'price import accepts dd.mm.yyyy dates'
ImportPrices = Pool().get('purchase_trade.import_prices')
result = ImportPrices._as_date('18.06.2026')
self.assertEqual(result, datetime.date(2026, 6, 18))
def test_pricing_component_matrix_returns_generic_line_price(self):
'matrix pricing can use an unconditional matrix line as a component price'
Component = Pool().get('pricing.component')