Правки финального ревью фазы 1: M-1, M-2, M-5
- M-1: поиск по перекрытым полям contract_summary (ооо лютик, дс-2, дс-1) и неперекрытому (70), явные assert для строки 910004 - M-2: в лог db_time вместо значений поиска и фильтров пишутся признаки has_*/search_len; unit-тест на caplog - M-5: total читается по имени столбца total_count Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
100dba4a90
commit
782a04381b
@ -188,10 +188,11 @@ async def get_summary2(
|
||||
"sort_by": sort_by,
|
||||
"sort_direction": sort_direction,
|
||||
"view": view,
|
||||
"search": search,
|
||||
"smeta_type": smeta_type,
|
||||
"smeta_direction": smeta_direction,
|
||||
"org_name": org_name,
|
||||
"has_search": bool(search),
|
||||
"search_len": len(search or ""),
|
||||
"has_smeta_type": bool(smeta_type),
|
||||
"has_smeta_direction": bool(smeta_direction),
|
||||
"has_org_name": bool(org_name),
|
||||
"user": current_user.id,
|
||||
}
|
||||
logger.info(f"db_time: {extra}", extra=extra)
|
||||
@ -244,10 +245,11 @@ async def get_summary2_facets(
|
||||
"sheet": sheet,
|
||||
"year": year,
|
||||
"org_ids": org_ids,
|
||||
"search": search,
|
||||
"smeta_type": smeta_type,
|
||||
"smeta_direction": smeta_direction,
|
||||
"org_name": org_name,
|
||||
"has_search": bool(search),
|
||||
"search_len": len(search or ""),
|
||||
"has_smeta_type": bool(smeta_type),
|
||||
"has_smeta_direction": bool(smeta_direction),
|
||||
"has_org_name": bool(org_name),
|
||||
"user": current_user.id,
|
||||
}
|
||||
logger.info(f"db_time: {extra}", extra=extra)
|
||||
|
||||
@ -136,7 +136,7 @@ class SummaryRepository:
|
||||
},
|
||||
)
|
||||
).all()
|
||||
total = int(result[0][4]) if result else 0
|
||||
total = int(result[0].total_count) if result else 0
|
||||
return [tuple(row[:4]) for row in result], total
|
||||
|
||||
async def get_svod2_facets(
|
||||
|
||||
@ -18,6 +18,7 @@ SMETA_TYPE_VARIANT = SMETA_TYPE.lower() + " "
|
||||
SEARCHES = [
|
||||
"аРЕНДА", "ё", "Ё", "ромаш", "лютик", "ромашка плюс", "1234.5", "1234.50", " аренда ",
|
||||
" ", "1", ",", "777.25", "<cd_id>", "я" * 5000,
|
||||
"ооо лютик", "дс-2", "дс-1", "70",
|
||||
]
|
||||
|
||||
FILTERS = {
|
||||
@ -140,6 +141,35 @@ def test_search_matches_screen_oracle(client, svod2_data, headers, sheet, search
|
||||
assert all(t == len(expected) for t in totals)
|
||||
|
||||
|
||||
# Строка 910004 имеет contract_summary (ООО Лютик, ДС-2, 70), но НЕ имеет contract_detail:
|
||||
# пустая секция contract_detail перекрывает counterparty/reference из contract_summary
|
||||
# (семантика экрана), а неперекрытое поле total_amount остаётся доступным для поиска.
|
||||
LINE_NO_DETAIL = 910004
|
||||
|
||||
|
||||
@pytest.mark.parametrize("sheet", SHEETS)
|
||||
@pytest.mark.parametrize("search", ["ооо лютик", "дс-2"])
|
||||
def test_search_overlapped_contract_summary_field_not_found(
|
||||
client, svod2_data, headers, sheet, search
|
||||
):
|
||||
full = legacy_full(client, sheet, headers)
|
||||
expected = screen_rows(full, search)
|
||||
assert LINE_NO_DETAIL not in _line_ids(expected)
|
||||
rows, _ = _all_pages(client, sheet, headers, 3, view="compact", search=search)
|
||||
assert LINE_NO_DETAIL not in _line_ids(rows)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("sheet", ["GO"])
|
||||
def test_search_non_overlapped_contract_summary_field_found(
|
||||
client, svod2_data, headers, sheet
|
||||
):
|
||||
full = legacy_full(client, sheet, headers)
|
||||
expected = screen_rows(full, "70")
|
||||
assert LINE_NO_DETAIL in _line_ids(expected)
|
||||
rows, _ = _all_pages(client, sheet, headers, 3, view="compact", search="70")
|
||||
assert LINE_NO_DETAIL in _line_ids(rows)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("sheet", SHEETS)
|
||||
@pytest.mark.parametrize("name", list(FILTERS))
|
||||
def test_filters_match_screen_oracle(client, svod2_data, headers, sheet, name):
|
||||
|
||||
60
api/tests/unit/test_summary2_log_privacy.py
Normal file
60
api/tests/unit/test_summary2_log_privacy.py
Normal file
@ -0,0 +1,60 @@
|
||||
"""Лог db_time не содержит значений поиска и фильтров (только признаки)."""
|
||||
import logging
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
from fastapi import Response
|
||||
|
||||
from src.api.v1 import summary as summary_api
|
||||
|
||||
SECRET = "СЕКРЕТНЫЙ-ПОИСК-123"
|
||||
FILTERS = {"smeta_type": "СЕКРЕТ-ТИП", "smeta_direction": "СЕКРЕТ-НАПР", "org_name": "СЕКРЕТ-ОРГ"}
|
||||
|
||||
|
||||
class _FakeService:
|
||||
def __init__(self, db):
|
||||
pass
|
||||
|
||||
async def get_svod2_page(self, **kwargs):
|
||||
return [], 0
|
||||
|
||||
async def get_svod2_facets(self, **kwargs):
|
||||
return {}
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _fake_service(monkeypatch):
|
||||
monkeypatch.setattr(summary_api, "SummaryService", _FakeService)
|
||||
monkeypatch.setattr(summary_api, "Svod2Facets", lambda **kw: kw, raising=False)
|
||||
|
||||
|
||||
def _assert_no_values(caplog):
|
||||
records = [r for r in caplog.records if getattr(r, "type", None) == "db_time"]
|
||||
assert records
|
||||
for r in records:
|
||||
text = r.getMessage() + repr(r.__dict__)
|
||||
for value in (SECRET, *FILTERS.values()):
|
||||
assert value not in text
|
||||
assert r.has_search is True
|
||||
assert r.search_len == len(SECRET)
|
||||
assert r.has_smeta_type and r.has_smeta_direction and r.has_org_name
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_page_log_has_no_search_values(caplog):
|
||||
caplog.set_level(logging.INFO)
|
||||
await summary_api.get_summary2(
|
||||
sheet="GO", year=2031, response=Response(), search=SECRET, db=None,
|
||||
current_user=SimpleNamespace(id=1), view="compact", **FILTERS,
|
||||
)
|
||||
_assert_no_values(caplog)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_facets_log_has_no_search_values(caplog):
|
||||
caplog.set_level(logging.INFO)
|
||||
await summary_api.get_summary2_facets(
|
||||
sheet="GO", year=2031, response=Response(), search=SECRET, db=None,
|
||||
current_user=SimpleNamespace(id=1), **FILTERS,
|
||||
)
|
||||
_assert_no_values(caplog)
|
||||
Loading…
x
Reference in New Issue
Block a user