Срез 2c: загрузка файлов ОСВ, цикл маппинга результата в document/osv_entry, API документов, DBML v5.15 #15

Merged
aep merged 35 commits from feat/14-slice-2c-osv-ingest into main 2026-10-06 00:56:15 +03:00
Showing only changes of commit f2324b15d3 - Show all commits

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}