ОСВ: названия ведомостей, группы и стороны других систем, «ВСЕГО» (#81)
AURORA-1717 (названия), AURORA-1719 (остатки, «по дебету», «Сальдо вх/исх», «ДТВВ»), AURORA-1732 («ВСЕГО»). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4d8f242990
commit
f5bb178899
@ -7,29 +7,51 @@
|
||||
# ведомость», «д т», `\w` вместо диапазона;
|
||||
# - новый синоним = новая строка в нужном списке, без правки кода.
|
||||
|
||||
# Лист содержит ОСВ: любая ячейка (первые строки листа) матчит один из паттернов
|
||||
# Лист содержит ОСВ: любая ячейка (первые строки листа) матчит один из паттернов. Названия других учётных систем и
|
||||
# отчётов 1С (AURORA-1717) — только с начала ячейки: «… см. оборотную ведомость» в примечании формы листом ОСВ не делает
|
||||
sheet_markers:
|
||||
- 'оборотно\s*сальдовая\s+ведомость'
|
||||
- '^оборотн\w*\s+ведомост' # «Оборотная ведомость по счетам …» (выгрузки КТЗ)
|
||||
- '^осв\b' # «ОСВ по сч. 41 за 3 кв.» (КТЗ)
|
||||
- '^оборотн\w*\s+баланс' # «Оборотный баланс» (КТЗ)
|
||||
- '^фин\.?\s*обороты' # «Фин. Обороты Листок» (Navision, Айсберри)
|
||||
- '^отчет\s+по\s+главной\s+книге' # SAP, ООО «Виола»
|
||||
|
||||
# Три группы сумм в заголовке таблицы. «Оборотно сальдовая» (название ведомости) не должно матчить turnover:
|
||||
# отсюда границы слова `\bоборот(ы)?\b`.
|
||||
# отсюда границы слова `\bоборот(ы)?\b`. Сторона может стоять в ячейке группы после названия — в том числе вплотную
|
||||
# («НачалоДт», «ОборотыДтВВ»): паттерн группы тогда заканчивается перед стороной (опережающая проверка), остаток ячейки
|
||||
# разбирают `debit`/`credit` (AURORA-1719)
|
||||
groups:
|
||||
opening:
|
||||
- 'сальдо\s+на\s+начало'
|
||||
- '\bнач(альн\w*)?\.?\s*сальдо'
|
||||
- 'входящ\w*\s+сальдо'
|
||||
- 'остат\w*\s+на\s+начало' # «Остаток на начало (периода)» (КТЗ)
|
||||
- 'остат\w*(?=\s+по\s+(дебету|кредиту)\s+на\s+начало)' # «Остаток по дебету на начало» (КТЗ, ЧАЗ)
|
||||
- 'сальдо\s+начальное' # «Сальдо НачальноеДТВВ» (SAP, НМЖК)
|
||||
- 'сальдо\s+вх\b' # «Сальдо вх Дт» (SAP, Виола)
|
||||
turnover:
|
||||
- '\bоборот(ы)?\b'
|
||||
- '^оборот(ы)?(?=\s*(дт|кт))' # «ОборотДт» (Navision), «ОборотыДтВВ» (SAP, НМЖК)
|
||||
closing:
|
||||
- 'сальдо\s+на\s+конец'
|
||||
- '\bкон(ечн\w*)?\.?\s*сальдо'
|
||||
- 'исходящ\w*\s+сальдо'
|
||||
- 'остат\w*\s+на\s+конец' # «Остаток на конец (периода)» (КТЗ)
|
||||
- 'остат\w*(?=\s+по\s+(дебету|кредиту)\s+на\s+конец)' # «Остаток по кредиту на конец» (КТЗ, ЧАЗ)
|
||||
- 'сальдо\s+конечное' # «Сальдо КонечноеКТВВ» (SAP, НМЖК)
|
||||
- 'сальдо\s+исх\b' # «Сальдо исх Кт» (SAP, Виола)
|
||||
|
||||
# Подзаголовки сумм под группой («Дебет»/«Кредит», «Дт»/«Кт», «Д-т»/«К-т»): ячейка начинается с синонима
|
||||
# Подзаголовки сумм под группой («Дебет»/«Кредит», «Дт»/«Кт», «Д-т»/«К-т») или сторона в остатке ячейки группы:
|
||||
# ячейка (остаток) начинается с синонима
|
||||
debit:
|
||||
- '^(дебет|дт|д т)\b'
|
||||
- '^по\s+дебету\b' # «Оборот по дебету», «Остаток по дебету на начало» (КТЗ)
|
||||
- '^дт\s*вв\b' # «Сальдо НачальноеДТВВ» (SAP, НМЖК)
|
||||
credit:
|
||||
- '^(кредит|кт|к т)\b'
|
||||
- '^по\s+кредиту\b' # «Оборот по кредиту» (КТЗ)
|
||||
- '^кт\s*вв\b' # «Сальдо НачальноеКТВВ» (SAP, НМЖК)
|
||||
|
||||
# Служебные колонки таблицы по тексту заголовка. Код знает колонки ИНН и «Показатели»; прочие колонки таблицы (КПП, код,
|
||||
# количество, валюта и т. п.) попадают в `rows[].extra` под текстом своего заголовка и словаря не требуют.
|
||||
@ -52,6 +74,8 @@ total_row_exact:
|
||||
- '^итого$'
|
||||
# выгрузка 1С «по контрагентам»: итог листа — «ИТОГ» (без «О»); «ИТОГ по 60.111» — итог субсчёта (subaccount_sums)
|
||||
- '^итог$'
|
||||
# «ВСЕГО» — итог листа ведомостей ГК КТЗ по счёту 009 (AURORA-1732)
|
||||
- '^всего$'
|
||||
|
||||
# Итог субсчёта в выгрузке 1С «по контрагентам»: «ИТОГ по 60.111» — суммы строки-счёта с тем же кодом (группа account);
|
||||
# отдельной строкой в результат не попадает (05-domain-rules.md §1.3, AURORA-1714)
|
||||
|
||||
@ -68,10 +68,8 @@ S55 = "s55_not_osv_titles.xlsx"
|
||||
S56 = "s56_almost_osv_tables.xlsx"
|
||||
S57 = "s57_form_mentions_osv.xlsx"
|
||||
OTHER_SYSTEMS_FILES = (S48, S49, S50, S51, S52, S53, S54, S55, S56, S57)
|
||||
PENDING_DICTIONARY = "tp#81 Task 2: словари названий, групп и сторон"
|
||||
PENDING_FALLBACK = "tp#81 Task 3: запасной признак листа по заголовку таблицы"
|
||||
PENDING_81 = {S48: PENDING_DICTIONARY, S49: PENDING_DICTIONARY, S50: PENDING_DICTIONARY, S53: PENDING_DICTIONARY}
|
||||
PENDING_81 |= {S51: PENDING_FALLBACK, S52: PENDING_FALLBACK, S54: PENDING_FALLBACK}
|
||||
PENDING_81 = {S51: PENDING_FALLBACK, S52: PENDING_FALLBACK, S54: PENDING_FALLBACK}
|
||||
S48_SHEETS = ("ОВ", "ОСВ сокр", "Оборотный баланс", "Навижн", "Главная книга", "Верхний регистр", "Вторая колонка")
|
||||
TYPO_ROW = 13 # строка «7701234567» с неверной контрольной суммой в s28
|
||||
EXPECTED_NAMES = [
|
||||
@ -865,7 +863,6 @@ def assert_done_with_sums(doc: OsvDocument, text: str, expected: tuple[Decimal |
|
||||
assert doc.rows[-1].group_type == "TOTAL"
|
||||
|
||||
|
||||
@pytest.mark.xfail(strict=True, reason=PENDING_DICTIONARY)
|
||||
def test_s48_other_system_titles_are_osv(fixtures_dir: Path) -> None:
|
||||
"""Каждое название ведомости — свой лист ОСВ; «ВСЕГО» и «Всего » — итоговая строка (AURORA-1717, 1732)."""
|
||||
outcome = parse_named(fixtures_dir, S48)
|
||||
@ -881,7 +878,6 @@ def test_s48_other_system_titles_are_osv(fixtures_dir: Path) -> None:
|
||||
assert not [text for text in warnings_of(outcome) if TOTAL_NOT_FOUND in text]
|
||||
|
||||
|
||||
@pytest.mark.xfail(strict=True, reason=PENDING_DICTIONARY)
|
||||
def test_s49_balance_and_turnover_by_side(fixtures_dir: Path) -> None:
|
||||
"""«Остаток на начало/конец», «Оборот по дебету/кредиту», «Остаток по дебету на начало»; преамбула «Остаток на
|
||||
начало: 0» над таблицей строкой групп не считается."""
|
||||
@ -893,7 +889,6 @@ def test_s49_balance_and_turnover_by_side(fixtures_dir: Path) -> None:
|
||||
assert_done_with_sums(second, "ООО Покупатель-1", BUYER_SUMS)
|
||||
|
||||
|
||||
@pytest.mark.xfail(strict=True, reason=PENDING_DICTIONARY)
|
||||
def test_s50_sap_in_out_and_glued_side(fixtures_dir: Path) -> None:
|
||||
"""SAP «Сальдо вх/исх Дт/Кт» и сторона, приклеенная к группе («ДТВВ»); «ООО Дтвв-Сервис» — контрагент."""
|
||||
outcome = parse_named(fixtures_dir, S50)
|
||||
@ -930,7 +925,6 @@ def test_s52_form_stays_form_navision_is_osv_reference_is_other(fixtures_dir: Pa
|
||||
assert_done_with_sums(one_document(outcome), ALFA, ALFA_SUMS)
|
||||
|
||||
|
||||
@pytest.mark.xfail(strict=True, reason=PENDING_DICTIONARY)
|
||||
def test_s53_xls_balance_by_side(fixtures_dir: Path) -> None:
|
||||
"""s49 в xls (без объединений): те же колонки и суммы."""
|
||||
outcome = parse_named(fixtures_dir, S53)
|
||||
|
||||
@ -282,6 +282,25 @@ def test_one_row_header_with_sides_in_group_cells(rules: Rules) -> None:
|
||||
assert [first_data_row(sheet, header)] == [3]
|
||||
|
||||
|
||||
def test_side_without_word_boundary_only_in_group_cell(rules: Rules) -> None:
|
||||
"""#81, SAP НМЖК: сторона приклеена к названию группы («Сальдо НачальноеДТВВ», «ОборотыДтВВ»); «Дтвв» в тексте
|
||||
контрагента ниже — не сторона и колонок не сдвигает."""
|
||||
sheet = sheet_from_rows(
|
||||
[
|
||||
[TITLE],
|
||||
["Счет", "Сальдо НачальноеДТВВ", "Сальдо НачальноеКТВВ", "ОборотыДтВВ", "ОборотыКтВВ"]
|
||||
+ ["Сальдо КонечноеДТВВ", "Сальдо КонечноеКТВВ"],
|
||||
[L(0), *at({1: "60", 2: 10, 7: 10})],
|
||||
[L(1), *at({1: "ООО Дтвв-Сервис", 2: 10, 7: 10})],
|
||||
]
|
||||
)
|
||||
|
||||
header = find_table_header(sheet, rules)
|
||||
|
||||
assert header.columns == ColumnMap(2, 3, 4, 5, 6, 7, frozenset())
|
||||
assert (header.first_row, header.last_row) == (2, 2)
|
||||
|
||||
|
||||
def test_unmerged_group_titles_take_subheaders_up_to_the_next_group(rules: Rules) -> None:
|
||||
sheet = sheet_from_rows(
|
||||
[
|
||||
|
||||
@ -330,10 +330,16 @@ def test_sheet_title_is_not_a_turnover_header(rules: Rules) -> None:
|
||||
|
||||
def test_initial_balance_synonym_is_not_in_the_default_dictionary(rules: Rules) -> None:
|
||||
# «Нач. остаток» добавляет сценарий «новый синоним без релиза кода» (R-8): в штатном словаре его быть не должно
|
||||
for text in ("Нач. остаток", "Начальный остаток", "Остаток на начало периода"):
|
||||
for text in ("Нач. остаток", "Начальный остаток"):
|
||||
assert not any(p.search(text) for p in rules.headers.groups["opening"]), text
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", ["остаток на начало периода", "остаток по дебету на начало", "сальдо вх дт"])
|
||||
def test_other_systems_opening_synonyms(rules: Rules, text: str) -> None:
|
||||
"""#81, AURORA-1719: написания группы «начало» выгрузок КТЗ и SAP (текст — нормализованный)."""
|
||||
assert any(p.search(text) for p in rules.headers.groups["opening"]), text
|
||||
|
||||
|
||||
@pytest.mark.parametrize("text", ["Дебет", "Дт", "Д-т", "дебет, руб."])
|
||||
def test_debit_synonyms(rules: Rules, text: str) -> None:
|
||||
assert any(p.search(text) for p in rules.headers.debit)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user