POST/GET /documents/{id}/comments, счётчик комментариев в карточке файла
и документа одним запросом на пачку документов.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
68 lines
3.5 KiB
Python
68 lines
3.5 KiB
Python
"""Комментарии к документу (spec documents-api «Комментарии к документу», «Файлы организации…»; D-11)."""
|
||
|
||
import pytest
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
from src.models.enums import DocumentStatus, FileStatus, RecognitionStatus
|
||
from tests.conftest import AuthClientFactory
|
||
from tests.factories import make_document, make_stored_file
|
||
from tests.test_api_documents import KA_RF, RKA, _rostov_entity
|
||
|
||
pytestmark = pytest.mark.integration
|
||
|
||
HTTP_OK = 200
|
||
HTTP_CREATED = 201
|
||
HTTP_FORBIDDEN = 403
|
||
HTTP_NOT_FOUND = 404
|
||
HTTP_UNPROCESSABLE = 422
|
||
COMMENTS_TOTAL = 2
|
||
|
||
|
||
async def _doc(session: AsyncSession, status: DocumentStatus = DocumentStatus.CONFIRMED):
|
||
entity = await _rostov_entity(session, name="ООО Комментарии")
|
||
file, job = await make_stored_file(
|
||
session, entity=entity, status=FileStatus.PROCESSED, job_status=RecognitionStatus.done
|
||
)
|
||
return file, await make_document(session, file=file, job=job, status=status)
|
||
|
||
|
||
async def test_add_and_list(seeded: AsyncSession, auth_client: AuthClientFactory) -> None:
|
||
file, document = await _doc(seeded)
|
||
client = await auth_client(KA_RF)
|
||
created = await client.post(f"/documents/{document.id}/comments", json={"text": " нет подписи руководителя "})
|
||
assert created.status_code == HTTP_CREATED, created.text
|
||
assert created.json()["text"] == "нет подписи руководителя"
|
||
assert created.json()["author"]["full_name"]
|
||
await client.post(f"/documents/{document.id}/comments", json={"text": "второй"})
|
||
listed = (await client.get(f"/documents/{document.id}/comments")).json()
|
||
assert [item["text"] for item in listed] == ["нет подписи руководителя", "второй"]
|
||
card = (await client.get(f"/files/{file.id}")).json()
|
||
assert card["documents"][0]["comments_count"] == COMMENTS_TOTAL
|
||
assert (await client.get(f"/documents/{document.id}")).json()["comments_count"] == COMMENTS_TOTAL
|
||
|
||
|
||
async def test_validation_and_rights(seeded: AsyncSession, auth_client: AuthClientFactory) -> None:
|
||
_, document = await _doc(seeded)
|
||
url = f"/documents/{document.id}/comments"
|
||
client = await auth_client(KA_RF)
|
||
assert (await client.post(url, json={"text": " "})).status_code == HTTP_UNPROCESSABLE
|
||
assert (await client.post(url, json={"text": "x" * 4001})).status_code == HTTP_UNPROCESSABLE
|
||
reader = await auth_client(RKA)
|
||
assert (await reader.post(url, json={"text": "можно?"})).status_code == HTTP_FORBIDDEN
|
||
assert (await reader.get(url)).status_code == HTTP_OK
|
||
stranger = await auth_client("client_manager@armka.local")
|
||
assert (await stranger.get(url)).status_code == HTTP_NOT_FOUND
|
||
|
||
|
||
async def test_comment_on_superseded_file(seeded: AsyncSession, auth_client: AuthClientFactory) -> None:
|
||
entity = await _rostov_entity(seeded, name="ООО Заменённый")
|
||
file, job = await make_stored_file(
|
||
session=seeded, entity=entity, status=FileStatus.SUPERSEDED, job_status=RecognitionStatus.done
|
||
)
|
||
document = await make_document(seeded, file=file, job=job, status=DocumentStatus.RECOGNIZED)
|
||
client = await auth_client(KA_RF)
|
||
created = await client.post(f"/documents/{document.id}/comments", json={"text": "архивная версия"})
|
||
assert created.status_code == HTTP_CREATED, created.text
|
||
listing = (await client.get(f"/legal-entities/{entity.id}/files", params={"include_superseded": "true"})).json()
|
||
assert listing["items"][0]["documents"][0]["comments_count"] == 1
|