Files
mostovik-backend/tests/apps/parsers/test_eis_registry_client.py
Aleksandr Meshchriakov c344bef777
All checks were successful
CI/CD Pipeline / Quality Gate (push) Successful in 28s
CI/CD Pipeline / Build and Push Images (push) Successful in 16s
CI/CD Pipeline / Internal Notify (push) Successful in 0s
CI/CD Pipeline / Deploy Dev via Compose (push) Successful in 23s
feat: restore registry procurement collection
2026-07-19 17:46:15 +02:00

125 lines
4.5 KiB
Python

from __future__ import annotations
from datetime import date
from decimal import Decimal
from urllib.parse import parse_qs, urlsplit
from apps.parsers.clients.base import HTTPClientError
from apps.parsers.clients.common.eis_registry import EisRegistryProcurementClient
from apps.parsers.clients.common.schemas import GenericParserItem
from django.test import SimpleTestCase
def _record(*, external_id: str, inn: str, amount: str = "1") -> GenericParserItem:
return GenericParserItem(
source="procurements_44fz",
external_id=external_id,
inn=inn,
organisation_name="Наименование из ЕИС",
title="Закупка",
amount=Decimal(amount),
payload={"raw": external_id},
)
class _FakeHttpClient:
def __init__(self, pages: dict[int, bytes], *, error_page: int | None = None):
self.pages = pages
self.error_page = error_page
self.urls: list[str] = []
def download_file(self, url: str, **_kwargs) -> bytes:
self.urls.append(url)
page = int(parse_qs(urlsplit(url).query)["pageNumber"][0])
if page == self.error_page:
raise HTTPClientError("page failed")
return self.pages[page]
class _FakeStructuredClient:
def __init__(self, pages: dict[int, bytes], records: dict[bytes, list]):
self.http_client = _FakeHttpClient(pages)
self.records = records
def fetch_records(self, *, content: bytes, file_name: str):
assert file_name == "results.html"
return self.records[content]
class EisRegistryProcurementClientTest(SimpleTestCase):
def test_fetches_all_pages_filters_inn_and_deduplicates_external_id(self):
page_1 = b'<a data-pagenumber="2"></a>'
page_2 = b'<a data-pagenumber="2"></a>'
structured = _FakeStructuredClient(
{1: page_1, 2: page_2},
{
page_1: [
_record(external_id="same", inn="7701000001", amount="1"),
_record(external_id="foreign", inn="7701000099"),
],
page_2: [
_record(external_id="same", inn="7701000001", amount="2"),
_record(external_id="other", inn="7701000001"),
],
},
)
client = EisRegistryProcurementClient(
source="procurements_44fz",
law="44",
_structured_client=structured,
)
records = client.fetch_for_customer(
inn="7701000001",
organization_name="ОПК Заказчик",
organization_id="org-1",
today=date(2026, 7, 19),
)
self.assertEqual([row.external_id for row in records], ["same", "other"])
self.assertEqual(records[0].amount, Decimal("2"))
self.assertTrue(all(row.inn == "7701000001" for row in records))
self.assertEqual(records[0].payload["organization_id"], "org-1")
query = parse_qs(urlsplit(structured.http_client.urls[0]).query)
self.assertEqual(query["fz44"], ["on"])
self.assertEqual(query["strictEqual"], ["true"])
self.assertEqual(query["publishDateFrom"], ["19.07.2025"])
self.assertEqual(query["publishDateTo"], ["19.07.2026"])
def test_builds_223fz_query_and_accepts_empty_page(self):
empty_page = b"<html></html>"
structured = _FakeStructuredClient({1: empty_page}, {empty_page: []})
client = EisRegistryProcurementClient(
source="procurements_223fz",
law="223",
_structured_client=structured,
)
records = client.fetch_for_customer(
inn="7701000001",
organization_name="ОПК Заказчик",
organization_id="org-1",
)
self.assertEqual(records, [])
query = parse_qs(urlsplit(structured.http_client.urls[0]).query)
self.assertEqual(query["fz223"], ["on"])
self.assertNotIn("fz44", query)
def test_page_error_is_not_silenced(self):
page_1 = b'<a data-pagenumber="2"></a>'
structured = _FakeStructuredClient({1: page_1}, {page_1: []})
structured.http_client.error_page = 2
client = EisRegistryProcurementClient(
source="procurements_44fz",
law="44",
_structured_client=structured,
)
with self.assertRaises(HTTPClientError):
client.fetch_for_customer(
inn="7701000001",
organization_name="ОПК Заказчик",
organization_id="org-1",
)