csv-parser: add _apply_mapping helper

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Giorgio Gilestro 2026-05-27 12:18:31 +02:00
parent f44b77df6f
commit b99f46d2fc
2 changed files with 146 additions and 1 deletions

View file

@ -152,3 +152,71 @@ def test_validate_mapping_non_numeric_qty_raises():
mapping = {"ticker_col": "Symbol", "qty_col": "Description"}
with pytest.raises(LLMParseError, match="numeric"):
_validate_mapping(mapping, headers, first_row)
def test_apply_mapping_builds_parsed_pie():
from app.services.csv_import import ParsedPie, ParsedPosition
from app.services.llm_csv_parser import _apply_mapping
headers = ["Symbol", "Quantity", "Avg Price", "Currency", "Description"]
data_rows = [
["AAPL", "100", "150.25", "USD", "Apple Inc"],
["MSFT", "50", "310.00", "USD", "Microsoft Corp"],
]
mapping = {
"ticker_col": "Symbol",
"qty_col": "Quantity",
"cost_col": "Avg Price",
"currency_col": "Currency",
"name_col": "Description",
}
pie = _apply_mapping(headers, data_rows, mapping)
assert isinstance(pie, ParsedPie)
assert len(pie.positions) == 2
p0 = pie.positions[0]
assert isinstance(p0, ParsedPosition)
assert p0.slice == "AAPL"
assert p0.name == "Apple Inc"
assert p0.quantity == 100.0
assert p0.invested_value == pytest.approx(15025.0)
# invested = qty * avg_cost = 100 * 150.25 = 15025
assert pie.invested == pytest.approx(15025.0 + 50 * 310.00)
def test_apply_mapping_handles_missing_optional_columns():
from app.services.llm_csv_parser import _apply_mapping
headers = ["Symbol", "Quantity"]
data_rows = [["AAPL", "100"]]
mapping = {
"ticker_col": "Symbol",
"qty_col": "Quantity",
"cost_col": None,
"currency_col": None,
"name_col": None,
}
pie = _apply_mapping(headers, data_rows, mapping)
p = pie.positions[0]
assert p.slice == "AAPL"
assert p.quantity == 100.0
assert p.invested_value is None
assert p.name == "AAPL" # falls back to ticker when name_col absent
def test_apply_mapping_skips_blank_and_unparseable_rows():
from app.services.llm_csv_parser import _apply_mapping
headers = ["Symbol", "Quantity"]
data_rows = [
["AAPL", "100"],
["", ""], # blank
["MSFT", "not-a-number"], # bad qty
["NVDA", "40"],
]
mapping = {"ticker_col": "Symbol", "qty_col": "Quantity"}
pie = _apply_mapping(headers, data_rows, mapping)
assert [p.slice for p in pie.positions] == ["AAPL", "NVDA"]