Add ERP explorer

This commit is contained in:
2026-07-29 14:03:06 +02:00
parent 720d789914
commit d92dc61277
6 changed files with 466 additions and 0 deletions
+152
View File
@@ -0,0 +1,152 @@
import json
from pathlib import Path
from article_data_manager.tools.erp_explorer import (
infer_value_type,
profile_erp_csv,
render_erp_profile_report,
write_erp_profile_report,
)
def write_text(path: Path, content: str) -> Path:
path.write_text(content, encoding="utf-8")
return path
def write_rollcalc_json(path: Path, article_numbers: list[str]) -> Path:
payload = [
{
"nr": nr,
"name": f"Article {nr}",
"thickness": 1.0,
"area_weight": 0.0,
"core_type": 0.0,
}
for nr in article_numbers
]
path.write_text(json.dumps(payload), encoding="utf-8")
return path
def test_profiles_columns(tmp_path: Path) -> None:
csv_path = write_text(
tmp_path / "erp.csv",
"\n".join(
[
"SL_ITEM_NO,ROP_PRODUCT_WIDTH,COMMENT,EMPTY_COLUMN",
"214700,\"6,00\",Alpha,",
"000123,1.20,Beta,",
"777777,,Alpha,",
]
),
)
profile = profile_erp_csv(csv_path)
assert profile.file_name == "erp.csv"
assert profile.row_count == 3
assert profile.column_count == 4
columns = {column.name: column for column in profile.columns}
assert columns["ROP_PRODUCT_WIDTH"].filled_count == 2
assert columns["ROP_PRODUCT_WIDTH"].empty_count == 1
assert columns["ROP_PRODUCT_WIDTH"].distinct_count == 2
assert columns["ROP_PRODUCT_WIDTH"].inferred_type == "decimal"
assert columns["COMMENT"].distinct_count == 2
assert columns["COMMENT"].inferred_type == "text"
assert columns["EMPTY_COLUMN"].inferred_type == "empty"
def test_infers_value_types() -> None:
assert infer_value_type([]) == "empty"
assert infer_value_type(["1", "002", "-3"]) == "integer"
assert infer_value_type(["1", "2.5", "3,75"]) == "decimal"
assert infer_value_type(["Alpha", "Beta"]) == "text"
assert infer_value_type(["1", "Alpha"]) == "mixed"
def test_detects_duplicate_article_numbers(tmp_path: Path) -> None:
csv_path = write_text(
tmp_path / "erp.csv",
"\n".join(
[
"SL_ITEM_NO,NAME",
"00001,A",
"1,B",
"00001,C",
"214700,D",
"214700,E",
]
),
)
article_numbers = profile_erp_csv(csv_path).article_numbers
assert article_numbers.distinct_count == 3
assert article_numbers.duplicate_count == 2
assert [(duplicate.nr, duplicate.count) for duplicate in article_numbers.duplicates] == [
("00001", 2),
("214700", 2),
]
def test_compares_rollcalc_articles_when_path_is_provided(tmp_path: Path) -> None:
csv_path = write_text(
tmp_path / "erp.csv",
"\n".join(
[
"SL_ITEM_NO,NAME",
"214700,A",
"000123,B",
]
),
)
rollcalc_path = write_rollcalc_json(tmp_path / "article-data.json", ["214700", "999999"])
comparison = profile_erp_csv(csv_path, rollcalc_path=rollcalc_path).rollcalc_comparison
assert comparison is not None
assert comparison.rollcalc_article_count == 2
assert comparison.found_count == 1
assert comparison.missing_count == 1
assert comparison.missing_article_numbers == ("999999",)
def test_rollcalc_comparison_is_optional(tmp_path: Path) -> None:
csv_path = write_text(
tmp_path / "erp.csv",
"\n".join(
[
"SL_ITEM_NO,NAME",
"214700,A",
]
),
)
assert profile_erp_csv(csv_path).rollcalc_comparison is None
def test_renders_and_writes_report(tmp_path: Path) -> None:
csv_path = write_text(
tmp_path / "erp.csv",
"\n".join(
[
"SL_ITEM_NO,ROP_PRODUCT_WIDTH",
"214700,\"6,00\"",
"214700,\"6,00\"",
]
),
)
report_path = tmp_path / "reports" / "erp_profile_report.txt"
profile = write_erp_profile_report(csv_path, report_path=report_path)
report = report_path.read_text(encoding="utf-8")
assert report == render_erp_profile_report(profile)
assert "ERP Profile Report" in report
assert "File: erp.csv" in report
assert "Rows: 2" in report
assert "Columns: 2" in report
assert "Column: ROP_PRODUCT_WIDTH" in report
assert "Duplicate article numbers" in report
assert "214700\t2" in report