csv-parser: add _apply_mapping helper
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
f44b77df6f
commit
b99f46d2fc
2 changed files with 146 additions and 1 deletions
|
|
@ -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"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue