"""Автоподтверждение чистых документов при маппинге результата (osv-result-mapping «Автоподтверждение чистого документа»; `05-domain-rules.md` §9.3, §9.5; OQ-157; design D-1–D-3 change `auto-confirm-clean-documents`). Документ, получивший при маппинге `RECOGNIZED` (ТЗ 03_9 п. 4: «при отсутствии замечаний — „Загружен“»), становится `CONFIRMED` от имени системы: `confirmed_by = NULL`, у формы `reviewed_by = NULL`, `audit_event(DOCUMENT_CONFIRM)` без пользователя. Привязка к версиям и переход версии — тот же хук, что у ручного подтверждения, с автором `stored_file.uploaded_by`. Вызывается в транзакции маппинга под заданием, файлом и документами (порядок блокировок D-5). """ import datetime from collections.abc import Sequence from sqlalchemy.ext.asyncio import AsyncSession from src.models.enums import AuditAction, AuditSection, DocumentStatus from src.models.files import Document, StoredFile from src.repositories import statements as statements_repo from src.services import consolidation_documents from src.services.audit import AuditService from src.services.statements import FORM_TYPES, form_confirmable AUTO_CONFIRM_DESCRIPTION = "автоподтверждение: без замечаний" OBJECT_TYPE = "document" def transition_comment(document: Document) -> str: """Комментарий перехода версии: «автоподтверждение документа <тип> [<счёт>]» (design решение №6).""" parts = ["автоподтверждение документа", document.document_type.value] if document.osv_account_code: parts.append(document.osv_account_code) return " ".join(parts) async def auto_confirm( session: AsyncSession, *, file: StoredFile, documents: Sequence[Document], now: datetime.datetime ) -> list[Document]: """Подтверждает документы `RECOGNIZED` файла (форма — только при `form_confirmable`, D-3); `NEEDS_CHECK` и прочие не трогает. Возвращает подтверждённые документы по возрастанию `id`.""" audit = AuditService(session) confirmed: list[Document] = [] for document in sorted(documents, key=lambda item: item.id): if document.status is not DocumentStatus.RECOGNIZED: continue if not await form_confirmable(session, document): continue document.status = DocumentStatus.CONFIRMED document.confirmed_by = None document.confirmed_at = now document.updated_at = now if document.document_type in FORM_TYPES: meta = await statements_repo.get_meta(session, document.id) if meta is not None: meta.reviewed_by = None meta.reviewed_at = now await session.flush() await consolidation_documents.on_document_confirmed( session, audit, document=document, changed_by=file.uploaded_by, comment=transition_comment(document), now=now, ) await audit.record( action=AuditAction.DOCUMENT_CONFIRM, section=AuditSection.PRIMARY_DOCUMENTS, object_type=OBJECT_TYPE, object_id=document.id, user_id=None, description=AUTO_CONFIRM_DESCRIPTION, before_value={"status": DocumentStatus.RECOGNIZED.value}, after_value={"status": DocumentStatus.CONFIRMED.value}, ) confirmed.append(document) return confirmed