arm-core/api/tests/test_convert_chart_1c.py
Andrey Epifancev 408dcaf3b0 feat(seed): конвертер плана счетов 1С в csv seed
Одноразовый скрипт api/scripts/convert_chart_1c.py: xlsx выгрузки 1С -> chart_of_accounts.csv
(иерархия по структуре кода, kind из «Вид», is_off_balance из «Заб.»).
ASSUMPTION(OQ-113): выгрузка считается полным планом счетов.

Refs #23

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Claude-Session: cedd7915-2efe-41e5-988c-a9117033598b
2026-10-06 12:57:20 +04:00

74 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Конвертер плана счетов 1С в csv seed (issue #23): иерархия по структуре кода, kind и забалансовость из выгрузки."""
from pathlib import Path
import pytest
from scripts.convert_chart_1c import ChartRow, convert, read_xlsx, write_csv
from scripts.seed import load_seed
API_DIR = Path(__file__).resolve().parent.parent
SEED_DIR = API_DIR / "seed"
CHART_SIZE = 488
XLSX = API_DIR.parent.parent / "fixtures" / "directories" / "chart-of-accounts-1c.xlsx"
def _rec(code: str, name: str = "Счёт", kind: str = "АП", off: str = "Нет") -> dict[str, object]:
return {"Код счета": code, "Наименование счета": name, "Вид": kind, "Заб.": off}
def test_convert_builds_hierarchy_kind_and_row_type() -> None:
rows = convert(
[_rec("01", kind="А"), _rec("01.К", kind="А"), _rec("76", kind="АП"), _rec("76.07"), _rec("76.07.1", kind="П")]
)
assert rows == [
ChartRow("01", "", "Счёт", "A", "account", False),
ChartRow("01.К", "01", "Счёт", "A", "subaccount", False),
ChartRow("76", "", "Счёт", "AP", "account", False),
ChartRow("76.07", "76", "Счёт", "AP", "subaccount", False),
ChartRow("76.07.1", "76.07", "Счёт", "P", "analytic", False),
]
def test_convert_off_balance_from_column_and_name_whitespace_collapsed() -> None:
(row,) = convert([_rec("МЦ", name=" Материальные ценности ", kind="А", off="Да")])
assert row.is_off_balance is True
assert row.name == "Материальные ценности"
def test_convert_orphan_without_any_ancestor_gets_empty_parent() -> None:
rows = convert([_rec("Я68.01"), _rec("Я69.06.5")])
assert [(r.code, r.parent_code, r.row_type) for r in rows] == [
("Я68.01", "", "subaccount"),
("Я69.06.5", "", "analytic"),
]
def test_convert_rejects_gap_in_hierarchy() -> None:
with pytest.raises(ValueError, match="более дальний предок"):
convert([_rec("76"), _rec("76.07.1")])
@pytest.mark.parametrize(
("records", "message"),
[
([_rec("01"), _rec("01")], "повторяются"),
([_rec("01", kind="Х")], "неизвестный вид"),
([_rec("01", off="да?")], "Да или Нет"),
([_rec("01", name=" ")], "пустое наименование"),
([_rec("01.01.1.1")], "глубина"),
],
)
def test_convert_rejects_bad_rows(records: list[dict[str, object]], message: str) -> None:
with pytest.raises(ValueError, match=message):
convert(records)
@pytest.mark.skipif(not XLSX.is_file(), reason="fixtures/directories/chart-of-accounts-1c.xlsx недоступен")
def test_repository_seed_matches_1c_export(tmp_path: Path) -> None:
"""Дрейф: seed/core/chart_of_accounts.csv побайтно равен результату конвертера на выгрузке 1С."""
out = tmp_path / "chart.csv"
write_csv(convert(read_xlsx(XLSX)), out)
assert out.read_text(encoding="utf-8") == (SEED_DIR / "core" / "chart_of_accounts.csv").read_text(encoding="utf-8")
assert len(load_seed(SEED_DIR).accounts) == CHART_SIZE