test: манифест реальных форм и Review Focus под общий код и v2.0 (#54)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BJKMLHdxMwSUeYcdkwqX4W
This commit is contained in:
parent
f5d071f602
commit
0f12c0eb3d
46
api/tests/fixtures/test_statements_property.py
vendored
46
api/tests/fixtures/test_statements_property.py
vendored
@ -17,29 +17,20 @@ EXPECTED_FILES = 18
|
|||||||
MAX_PARSE_SECONDS = 5
|
MAX_PARSE_SECONDS = 5
|
||||||
|
|
||||||
|
|
||||||
def document_ok(document: StatementDocument) -> bool:
|
|
||||||
"""Документ пригоден (done): критерий `StatementParser._is_ok`, выраженный полями результата."""
|
|
||||||
if document.document_type == "DISCLOSURE":
|
|
||||||
return True
|
|
||||||
checks = document.checks
|
|
||||||
return (
|
|
||||||
checks is not None
|
|
||||||
and bool(document.columns)
|
|
||||||
and bool(document.header.organization_name or document.header.inn)
|
|
||||||
and not checks.relations_failed
|
|
||||||
and not checks.duplicate_line_codes
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def explained_needs_check(document: StatementDocument) -> bool:
|
def explained_needs_check(document: StatementDocument) -> bool:
|
||||||
"""Причина needs_check видна в результате: нарушенное соотношение, дубликаты кодов, нет колонок или шапки."""
|
"""Причина needs_check видна в результате: предупреждение error, нарушенное соотношение, пометка проверки
|
||||||
|
у строки, значения или шапки, нечитаемая или пропущенная строка."""
|
||||||
checks = document.checks
|
checks = document.checks
|
||||||
return bool(
|
return bool(
|
||||||
checks is None
|
any(warning.severity == "error" for warning in document.warnings)
|
||||||
or checks.relations_failed
|
or (checks is not None and checks.relations_failed)
|
||||||
or checks.duplicate_line_codes
|
or document.header.needs_review_fields
|
||||||
or not document.columns
|
or any(
|
||||||
or not (document.header.organization_name or document.header.inn)
|
line.needs_review
|
||||||
|
or line.line_status in ("unreadable", "missing")
|
||||||
|
or any(value.needs_review for value in line.values)
|
||||||
|
for line in document.lines
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -61,23 +52,26 @@ def test_statement_file_matches_manifest(fixtures_dir: Path, statement_file: Pat
|
|||||||
all_done = all(item.status == "done" for item in expectation.documents)
|
all_done = all(item.status == "done" for item in expectation.documents)
|
||||||
assert outcome.status is (ResultStatus.DONE if all_done else ResultStatus.NEEDS_CHECK)
|
assert outcome.status is (ResultStatus.DONE if all_done else ResultStatus.NEEDS_CHECK)
|
||||||
for document, item in zip(documents, expectation.documents, strict=True):
|
for document, item in zip(documents, expectation.documents, strict=True):
|
||||||
codes = [line.line_code for line in document.lines]
|
# повторы кодов строк законны (v2.0); ссылки на строки уникальны, значения ссылаются на колонки документа
|
||||||
assert len(codes) == len(set(codes)), "коды уникальны"
|
refs = [line.ref for line in document.lines]
|
||||||
assert all(value.column_index < len(document.columns) for line in document.lines for value in line.values)
|
assert len(refs) == len(set(refs)), "ref уникальны"
|
||||||
|
column_indexes = {column.column_index for column in document.columns}
|
||||||
|
assert all(value.column_index in column_indexes for line in document.lines for value in line.values)
|
||||||
if item.sheets:
|
if item.sheets:
|
||||||
assert document.locator.count(",") == item.sheets - 1
|
assert document.locator.count(",") == item.sheets - 1
|
||||||
failed = {relation.relation for relation in document.checks.relations_failed} if document.checks else set()
|
failed = {relation.relation for relation in document.checks.relations_failed} if document.checks else set()
|
||||||
if item.failed_relations is not None:
|
if item.failed_relations is not None:
|
||||||
assert failed == set(item.failed_relations)
|
assert failed == set(item.failed_relations)
|
||||||
|
if item.error_warnings is not None:
|
||||||
|
errors = {warning.code for warning in document.warnings if warning.severity == "error"}
|
||||||
|
assert errors == set(item.error_warnings)
|
||||||
if item.complete:
|
if item.complete:
|
||||||
assert document.checks is not None
|
assert document.checks is not None
|
||||||
assert document.checks.relations_failed == [], document.checks
|
assert document.checks.relations_failed == [], document.checks
|
||||||
assert document.columns
|
assert document.columns
|
||||||
assert all(column.period_date is not None for column in document.columns)
|
assert all(column.period_date is not None for column in document.columns)
|
||||||
# статус документа — по критерию парсера (statement.py::_is_ok), независимо от манифеста
|
assert document.status == item.status, (item, document.header)
|
||||||
assert document_ok(document) == (item.status == "done"), (item, document.header)
|
|
||||||
if item.status == "needs_check":
|
if item.status == "needs_check":
|
||||||
assert not document_ok(document)
|
|
||||||
assert explained_needs_check(document), "needs_check должен объясняться полями результата"
|
assert explained_needs_check(document), "needs_check должен объясняться полями результата"
|
||||||
if expectation.organization:
|
if expectation.organization:
|
||||||
assert document.header.organization_name == expectation.organization
|
assert document.header.organization_name == expectation.organization
|
||||||
|
|||||||
66
api/tests/fixtures/test_statements_real.py
vendored
Normal file
66
api/tests/fixtures/test_statements_real.py
vendored
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
"""Review Focus плана 4 на реальных книгах `../fixtures/statements-xlsx/**` (спека «Манифест ожиданий...»)."""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from src.contract import FileType, StatementDocument
|
||||||
|
from src.parser import get_parser
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.fixtures
|
||||||
|
STATEMENTS = "statements-xlsx"
|
||||||
|
TITLE_BLOCK_FILES = [
|
||||||
|
"unagrande-co/2024-FY/Б.Б Лист 1.xls",
|
||||||
|
"unagrande-co/2024-FY/ОФР. Лист 1.xls",
|
||||||
|
"unagrande-group/2024-FY/ББ. Лист 1 .xls",
|
||||||
|
"unagrande-group/2025-Q3/ББ. Лист 1 3кв.25.xls",
|
||||||
|
"unagrande-group/2025-Q3/ОФР. Лист 1 3кв.25.xls",
|
||||||
|
]
|
||||||
|
NPZ = "npz/2025-Q3/Бухгалтерская отчетность за Январь - Сентябрь 2025 г. (НОВОРОССИЙСКИЙ ПРОКАТНЫЙ ЗАВОД).xlsx"
|
||||||
|
MEZHENINOVSKAYA = [
|
||||||
|
"mezheninovskaya/2025-Q3/1_Форма1_бух_09.xlsx",
|
||||||
|
"mezheninovskaya/2025-Q3/1_Форма2_бух_09.xlsx",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def statement_docs(fixtures_dir: Path, key: str) -> list[StatementDocument]:
|
||||||
|
path = fixtures_dir / STATEMENTS / key
|
||||||
|
outcome = get_parser().parse(path.read_bytes(), cast(FileType, path.suffix.lstrip(".").upper()))
|
||||||
|
assert outcome.error is None, outcome.error
|
||||||
|
return [document for document in outcome.documents if isinstance(document, StatementDocument)]
|
||||||
|
|
||||||
|
|
||||||
|
def test_unagrande_title_codes_block(fixtures_dir: Path) -> None:
|
||||||
|
"""Review Focus 1: ОКОПФ из блока кодов шапки не становится строкой формы."""
|
||||||
|
for key in TITLE_BLOCK_FILES:
|
||||||
|
for doc in statement_docs(fixtures_dir, key):
|
||||||
|
assert doc.header.okopf == "12267", key
|
||||||
|
assert not any("12267" in (line.line_code_text or "") for line in doc.lines), key
|
||||||
|
|
||||||
|
|
||||||
|
def test_npz_documents(fixtures_dir: Path) -> None:
|
||||||
|
"""Review Focus 2; спека «НПЗ «Реализация иного имущества»»."""
|
||||||
|
balance, income = statement_docs(fixtures_dir, NPZ)
|
||||||
|
assert (balance.status, income.status) == ("done", "done")
|
||||||
|
bad = {"SHEET_NOT_JOINED", "SEGMENT_COLUMNS_MISMATCH", "SEGMENT_WITHOUT_CODES", "HEADER_ROW_NOT_FOUND"}
|
||||||
|
assert not bad & {w.code for d in (balance, income) for w in d.warnings}
|
||||||
|
cols = {c.column_index for c in balance.columns}
|
||||||
|
assert all(v.column_index in cols for line in balance.lines for v in line.values)
|
||||||
|
income_cols = {c.column_index for c in income.columns}
|
||||||
|
assert all(v.column_index in income_cols for line in income.lines for v in line.values)
|
||||||
|
# Строки F34/F44 «Реализация иного имущества…» состоят только из прочерков (0 с форматом `[=0]"-"`, value None):
|
||||||
|
# по спеке строка без кода и без содержимого — не строка данных, пакет её не выдаёт (R-10; вопрос владельцу O-8.2:
|
||||||
|
# сценарий спеки «с суммами» не соответствует файлу, где суммы — прочерки).
|
||||||
|
assert any(
|
||||||
|
line.line_code == "2400" and line.ref.startswith("'Отчет о финансовых результата_2'") for line in income.lines
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_mezheninovskaya_numbering_and_signatures(fixtures_dir: Path) -> None:
|
||||||
|
"""Review Focus 3: строка нумерации колонок «2» и подписи не становятся строками формы."""
|
||||||
|
for key in MEZHENINOVSKAYA:
|
||||||
|
(doc,) = statement_docs(fixtures_dir, key)
|
||||||
|
assert doc.status == "done" and doc.header.inn == "7016006635", key
|
||||||
|
assert not any(line.line_code_text == "2" for line in doc.lines), key
|
||||||
|
assert not any(line.line_status in ("unreadable", "missing") for line in doc.lines), key
|
||||||
@ -20,6 +20,7 @@ class DocumentExpectation(BaseModel):
|
|||||||
reason: str | None = None
|
reason: str | None = None
|
||||||
sheets: int | None = None
|
sheets: int | None = None
|
||||||
failed_relations: list[str] | None = None # None — не проверяется; список — точное множество relations_failed
|
failed_relations: list[str] | None = None # None — не проверяется; список — точное множество relations_failed
|
||||||
|
error_warnings: list[str] | None = None # None — не проверяется; список — точное множество кодов уровня error
|
||||||
|
|
||||||
|
|
||||||
class Expectation(BaseModel):
|
class Expectation(BaseModel):
|
||||||
|
|||||||
@ -1,66 +1,69 @@
|
|||||||
# Ожидания по реальным формам fixtures/statements-xlsx/** (README там же). Ключ — путь относительно statements-xlsx.
|
# Ожидания по реальным формам fixtures/statements-xlsx/** (README там же). Ключ — путь относительно statements-xlsx.
|
||||||
# documents — по порядку документов результата: type, status (done | needs_check), complete (вся форма: §7 сходится).
|
# documents — по порядку документов результата: type, status (done | needs_check), complete (вся форма: §7 сходится).
|
||||||
|
# error_warnings — точное множество кодов предупреждений документа уровня error (P4-18); отсутствие поля — не проверяется.
|
||||||
# Причина needs_check — данные файла (страница без шапки, шаблон без сумм), не дефект разбора.
|
# Причина needs_check — данные файла (страница без шапки, шаблон без сумм), не дефект разбора.
|
||||||
# Значения сверены прогоном парсера на файлах (R-13): расхождения с первоначальным планом помечены «по факту».
|
# Значения сверены прогоном парсера на файлах (R-13): расхождения с первоначальным планом помечены «по факту».
|
||||||
# Значения ББ/ОФР — как их показывает числовой формат ячейки (#42): рубли с копейками из 1С приходят в тысячах;
|
# Значения ББ/ОФР — как их показывает числовой формат ячейки (#42): рубли с копейками из 1С приходят в тысячах;
|
||||||
# мягкие нарушения (в пределах допуска округления, OQ-138) статус не меняют; набор — по факту разбора, см. golden.
|
# мягкие нарушения (в пределах допуска округления, OQ-138) статус не меняют; набор — по факту разбора, см. golden.
|
||||||
|
# Страница 2 без шапки: организации и ИНН нет (NO_ORGANIZATION_NO_INN), а 1600 = 1700 не сходится, потому что актив
|
||||||
|
# на странице 1, а пассив на странице 2 (v2.0: проверка идёт по самой странице).
|
||||||
files:
|
files:
|
||||||
"unagrande-co/2024-FY/Б.Б Лист 1.xls":
|
"unagrande-co/2024-FY/Б.Б Лист 1.xls":
|
||||||
organization: 'Акционерное общество "Унагранде Компани"'
|
organization: 'Акционерное общество "Унагранде Компани"'
|
||||||
inn: "3249004697"
|
inn: "3249004697"
|
||||||
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "только актив: 1600 = 1700 не сходится", failed_relations: ["1600 = 1700"]}]
|
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "только актив: 1600 = 1700 не сходится", failed_relations: ["1600 = 1700"], error_warnings: []}]
|
||||||
"unagrande-co/2024-FY/Б.Б. Лист 2.xls":
|
"unagrande-co/2024-FY/Б.Б. Лист 2.xls":
|
||||||
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: []}]
|
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: ["1600 = 1700"], error_warnings: [NO_ORGANIZATION_NO_INN]}]
|
||||||
"unagrande-co/2024-FY/ОФР. Лист 1.xls":
|
"unagrande-co/2024-FY/ОФР. Лист 1.xls":
|
||||||
organization: 'Акционерное общество "Унагранде Компани"'
|
organization: 'Акционерное общество "Унагранде Компани"'
|
||||||
inn: "3249004697"
|
inn: "3249004697"
|
||||||
documents:
|
documents:
|
||||||
- {type: INCOME, status: done, complete: true, failed_relations: []} # значения по формату в тыс. руб.; мягко расходится 2400 = 2300 - 2410 + 2420 (в пределах допуска, OQ-138)
|
- {type: INCOME, status: done, complete: true, failed_relations: [], error_warnings: []} # значения по формату в тыс. руб.; мягко расходится 2400 = 2300 - 2410 + 2420 (в пределах допуска, OQ-138)
|
||||||
"unagrande-co/2024-FY/ОФР. Лист 2 .xls":
|
"unagrande-co/2024-FY/ОФР. Лист 2 .xls":
|
||||||
documents: [{type: INCOME, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: []}]
|
documents: [{type: INCOME, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: [], error_warnings: [NO_ORGANIZATION_NO_INN]}]
|
||||||
"unagrande-group/2024-FY/ББ. Лист 1 .xls":
|
"unagrande-group/2024-FY/ББ. Лист 1 .xls":
|
||||||
organization: 'Акционерное общество "Унагранде Групп"'
|
organization: 'Акционерное общество "Унагранде Групп"'
|
||||||
inn: "7728757141"
|
inn: "7728757141"
|
||||||
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "только актив", failed_relations: ["1600 = 1700"]}]
|
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "только актив", failed_relations: ["1600 = 1700"], error_warnings: []}]
|
||||||
"unagrande-group/2024-FY/ББ. Лист 2 (2).xls":
|
"unagrande-group/2024-FY/ББ. Лист 2 (2).xls":
|
||||||
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: []}]
|
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: ["1600 = 1700"], error_warnings: [NO_ORGANIZATION_NO_INN]}]
|
||||||
"unagrande-group/2024-FY/ОФР. Лист 2.xls":
|
"unagrande-group/2024-FY/ОФР. Лист 2.xls":
|
||||||
documents: [{type: INCOME, status: needs_check, complete: false, reason: "страница 2 без шапки, стр. 1 в пакете нет", failed_relations: []}]
|
documents: [{type: INCOME, status: needs_check, complete: false, reason: "страница 2 без шапки, стр. 1 в пакете нет", failed_relations: [], error_warnings: [NO_ORGANIZATION_NO_INN]}]
|
||||||
"unagrande-group/2025-Q3/ББ. Лист 1 3кв.25.xls":
|
"unagrande-group/2025-Q3/ББ. Лист 1 3кв.25.xls":
|
||||||
organization: 'Акционерное общество "Унагранде Групп"'
|
organization: 'Акционерное общество "Унагранде Групп"'
|
||||||
inn: "7728757141"
|
inn: "7728757141"
|
||||||
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "только актив", failed_relations: ["1600 = 1700"]}]
|
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "только актив", failed_relations: ["1600 = 1700"], error_warnings: []}]
|
||||||
"unagrande-group/2025-Q3/ББ. Лист 2 3кв.25.xls":
|
"unagrande-group/2025-Q3/ББ. Лист 2 3кв.25.xls":
|
||||||
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: []}]
|
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: ["1600 = 1700"], error_warnings: [NO_ORGANIZATION_NO_INN]}]
|
||||||
"unagrande-group/2025-Q3/ОФР. Лист 1 3кв.25.xls":
|
"unagrande-group/2025-Q3/ОФР. Лист 1 3кв.25.xls":
|
||||||
organization: 'Акционерное общество "Унагранде Групп"'
|
organization: 'Акционерное общество "Унагранде Групп"'
|
||||||
inn: "7728757141"
|
inn: "7728757141"
|
||||||
documents:
|
documents:
|
||||||
- {type: INCOME, status: done, complete: true, failed_relations: []} # мягко расходятся 2400 = 2300 - 2410 + 2420 и 2410 = 2411 + 2412 (в пределах допуска, OQ-138)
|
- {type: INCOME, status: done, complete: true, failed_relations: [], error_warnings: []} # мягко расходятся 2400 = 2300 - 2410 + 2420 и 2410 = 2411 + 2412 (в пределах допуска, OQ-138)
|
||||||
"unagrande-group/2025-Q3/ОФР. Лист 2 3кв.25.xls":
|
"unagrande-group/2025-Q3/ОФР. Лист 2 3кв.25.xls":
|
||||||
documents: [{type: INCOME, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: []}]
|
documents: [{type: INCOME, status: needs_check, complete: false, reason: "страница 2 без шапки", failed_relations: [], error_warnings: [NO_ORGANIZATION_NO_INN]}]
|
||||||
"npz/2025-Q3/Бухгалтерская отчетность за Январь - Сентябрь 2025 г. (НОВОРОССИЙСКИЙ ПРОКАТНЫЙ ЗАВОД).xlsx":
|
"npz/2025-Q3/Бухгалтерская отчетность за Январь - Сентябрь 2025 г. (НОВОРОССИЙСКИЙ ПРОКАТНЫЙ ЗАВОД).xlsx":
|
||||||
organization: 'ООО "НОВОРОССИЙСКИЙ ПРОКАТНЫЙ ЗАВОД"'
|
organization: 'ООО "НОВОРОССИЙСКИЙ ПРОКАТНЫЙ ЗАВОД"'
|
||||||
inn: "2315995868"
|
inn: "2315995868"
|
||||||
inn_optional_for: [INCOME]
|
inn_optional_for: [INCOME]
|
||||||
documents:
|
documents:
|
||||||
- {type: BALANCE, status: done, complete: true, sheets: 5, failed_relations: []} # мягко расходятся детализации 1150, 1250, 1410, 1500, 1510 (сверка с итогом в самой выгрузке, OQ-138)
|
- {type: BALANCE, status: done, complete: true, sheets: 5, failed_relations: [], error_warnings: []} # мягко расходятся детализации 1150, 1250, 1410, 1500, 1510 (сверка с итогом в самой выгрузке, OQ-138)
|
||||||
- {type: INCOME, status: done, complete: true, sheets: 3, failed_relations: []} # мягко расходятся 2400 и 2410 (OQ-138); лист с единственной строкой 2400 присоединён (O-9)
|
- {type: INCOME, status: done, complete: true, sheets: 3, failed_relations: [], error_warnings: []} # мягко расходятся 2400 и 2410 (OQ-138); лист с единственной строкой 2400 присоединён (O-9)
|
||||||
"mezheninovskaya/2025-Q3/1_Форма1_бух_09.xlsx":
|
"mezheninovskaya/2025-Q3/1_Форма1_бух_09.xlsx":
|
||||||
organization: 'ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ "АГРОФИРМА "МЕЖЕНИНОВСКАЯ"'
|
organization: 'ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ "АГРОФИРМА "МЕЖЕНИНОВСКАЯ"'
|
||||||
inn: "7016006635"
|
inn: "7016006635"
|
||||||
documents: [{type: BALANCE, status: done, complete: true, failed_relations: []}]
|
documents: [{type: BALANCE, status: done, complete: true, failed_relations: [], error_warnings: []}] # колонки сумм M/Q/S; числа правее таблицы формы — NUMBERS_OUTSIDE_TABLE (info, Р-44)
|
||||||
"mezheninovskaya/2025-Q3/1_Форма2_бух_09.xlsx":
|
"mezheninovskaya/2025-Q3/1_Форма2_бух_09.xlsx":
|
||||||
organization: 'ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ "АГРОФИРМА "МЕЖЕНИНОВСКАЯ"'
|
organization: 'ОБЩЕСТВО С ОГРАНИЧЕННОЙ ОТВЕТСТВЕННОСТЬЮ "АГРОФИРМА "МЕЖЕНИНОВСКАЯ"'
|
||||||
inn: "7016006635"
|
inn: "7016006635"
|
||||||
documents: [{type: INCOME, status: done, complete: true, failed_relations: []}]
|
documents: [{type: INCOME, status: done, complete: true, failed_relations: [], error_warnings: []}]
|
||||||
"templates/ББ до 01.01.2025.xlsx":
|
"templates/ББ до 01.01.2025.xlsx":
|
||||||
documents:
|
documents:
|
||||||
- {type: BALANCE, status: needs_check, complete: false, reason: "шаблон без сумм и шапки", failed_relations: []}
|
- {type: BALANCE, status: needs_check, complete: false, reason: "шаблон без сумм и шапки", failed_relations: [], error_warnings: [NO_ORGANIZATION_NO_INN, PERIOD_UNKNOWN, SEGMENT_COLUMNS_MISMATCH]}
|
||||||
- {type: DISCLOSURE, status: done, complete: false, reason: "по факту: «Примечания» шаблона образуют пустой документ DISCLOSURE"}
|
- {type: DISCLOSURE, status: done, complete: false, reason: "по факту: «Примечания» шаблона образуют пустой документ DISCLOSURE", error_warnings: []}
|
||||||
"templates/ББ после 01.01.2025.xlsx":
|
"templates/ББ после 01.01.2025.xlsx":
|
||||||
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "шаблон", failed_relations: []}]
|
documents: [{type: BALANCE, status: needs_check, complete: false, reason: "шаблон", failed_relations: [], error_warnings: [PERIOD_UNKNOWN]}]
|
||||||
"templates/ОФР_до 01.01.2025.xlsx":
|
"templates/ОФР_до 01.01.2025.xlsx":
|
||||||
documents: [{type: INCOME, status: needs_check, complete: false, reason: "шаблон", failed_relations: []}]
|
documents: [{type: INCOME, status: needs_check, complete: false, reason: "шаблон", failed_relations: [], error_warnings: [NO_ORGANIZATION_NO_INN, PERIOD_UNKNOWN]}]
|
||||||
"templates/ОФР_после 01.01.2025.xlsx":
|
"templates/ОФР_после 01.01.2025.xlsx":
|
||||||
documents: [{type: INCOME, status: needs_check, complete: false, reason: "шаблон", failed_relations: []}]
|
documents: [{type: INCOME, status: needs_check, complete: false, reason: "шаблон", failed_relations: [], error_warnings: [PERIOD_UNKNOWN]}]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user