test(mapping): автозамена нескольких файлов одним новым — N событий, version_no = max + 1

Ревью T8.1: новый файл с ОСВ 60/62/66 заменяет три прежних файла с version_no 1, 3, 2 по
возрастанию id (максимум в середине порядка блокировки) → три FILE_REPLACE, version_no = 4.
Мутации `locked[0]` / `locked[-1]` вместо max тест ловит.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
This commit is contained in:
Andrey Epifancev 2026-10-05 23:18:57 +04:00
parent dff448d464
commit f2324b15d3

View File

@ -980,3 +980,43 @@ async def test_one_event_per_replaced_file(committed_sessionmaker: async_session
assert "OSV 60 2025 Q1 (CONFIRMED)" in event.description
assert "OSV 62 2025 Q1 (NEEDS_CHECK)" in event.description
assert "confirmed=true" in event.description
async def test_new_file_supersedes_several_files(committed_sessionmaker: async_sessionmaker[AsyncSession]):
"""Один новый файл (ОСВ 60, 62, 66) заменяет три разных прежних файла: событие `FILE_REPLACE` на каждый заменённый
файл, у нового `version_no` = МАКСИМУМ заменённых + 1. Версии раздаются по возрастанию `id` как 1, 3, 2: максимум —
в середине порядка блокировки, поэтому ни первый, ни последний заблокированный файл его не дают."""
maker, storage = committed_sessionmaker, FakeStorage()
entity_id = await _entity(maker)
old_ids = [
await _old_file(maker, entity_id, [(account, 2025, PeriodQuarter.Q1, DocumentStatus.RECOGNIZED)])
for account in ("60", "62", "66")
]
ordered = sorted(old_ids)
versions = dict(zip(ordered, (1, 3, 2), strict=True))
async with maker() as session, session.begin():
for file_id, version_no in versions.items():
file = await session.get(StoredFile, file_id)
assert file is not None
file.version_no = version_no
result = _minimal()
for number, account in enumerate(("62", "66"), start=2):
sheet = copy.deepcopy(_osv(result)) | {"locator": f"sheet:Лист_{number}"}
sheet["header"]["account_code_raw"] = account
result["documents"].append(sheet)
async with maker() as session:
entity = await session.get(LegalEntity, entity_id)
new_id, _, _ = await _prepare(maker, storage, result, entity=entity)
assert await process_once(maker, storage, _settings()) is True
expected_version = 4 # max(1, 3, 2) + 1
for old_id in old_ids:
old = await _file(maker, old_id)
assert (old.status, old.superseded_by_file_id) == (FileStatus.SUPERSEDED, new_id)
assert (await _file(maker, new_id)).version_no == expected_version
events = await _replace_events(maker)
assert sorted(event.object_id for event in events) == ordered # type: ignore[type-var]
for event in events:
assert event.user_id is None
assert event.after_value == {"file_id": str(new_id), "version_no": expected_version}