from __future__ import annotations from apps.parsers.clients.base import HTTPClientError from apps.parsers.clients.common.structured import ( EIS_CA_BUNDLE_PATH, StructuredDataClient, ) from django.test import SimpleTestCase class _FakeHTTPClient: def __init__(self, responses: dict[str, bytes | Exception]) -> None: self.responses = responses self.downloaded_urls: list[str] = [] def download_file(self, endpoint: str, **_kwargs) -> bytes: self.downloaded_urls.append(endpoint) response = self.responses[endpoint] if isinstance(response, Exception): raise response return response class _FakeGispHTTPClient: def __init__(self) -> None: self.endpoint = "" self.payload: dict | None = None def post_json( self, endpoint: str, *, payload: dict | None = None, **_kwargs, ) -> dict: self.endpoint = endpoint self.payload = payload return {"items": [{"res_number": "123", "_product_name": "Станок"}]} class StructuredDataClientGispTest(SimpleTestCase): def test_products_request_omits_unsupported_res_date_sort(self): client = StructuredDataClient(source="mpt_products") fake_http_client = _FakeGispHTTPClient() client._http_client = fake_http_client records = client.fetch_records(file_url="https://gisp.gov.ru/pp719v2/pub/prod/") self.assertEqual(len(records), 1) self.assertEqual(records[0].external_id, "123") self.assertEqual( fake_http_client.endpoint, "https://gisp.gov.ru/pp719v2/pub/prod/b/", ) self.assertEqual( fake_http_client.payload, { "opt": { "skip": 0, "take": 100, "requireTotalCount": True, } }, ) class StructuredDataClientFasGozParsingTest(SimpleTestCase): def test_person_name_populates_record_title(self): client = StructuredDataClient(source="fas_goz") records = client.fetch_records( content="""
РГОЗ-001 ФАС России Постановление № 1 14.07.2026 Исполнено ООО ПРОГРЕСС ПРОГРЕСС г. Москва 7707083893
""".encode(), file_name="register.html", ) self.assertEqual(len(records), 1) self.assertEqual(records[0].organisation_name, "ООО ПРОГРЕСС") self.assertEqual(records[0].title, "ООО ПРОГРЕСС") class StructuredDataClientEisCardEnrichmentTest(SimpleTestCase): def test_eis_client_uses_project_scoped_trusted_ca_bundle(self): client = StructuredDataClient(source="procurements_44fz") self.assertTrue(EIS_CA_BUNDLE_PATH.is_file()) self.assertEqual(client.http_client.verify_ssl, str(EIS_CA_BUNDLE_PATH)) def test_procurement_card_enriches_customer_identity_from_detail_page(self): detail_url = ( "https://zakupki.gov.ru/epz/order/notice/ea20/view/" "common-info.html?regNumber=0338100002026000022" ) client = StructuredDataClient(source="procurements_44fz") client._http_client = _FakeHTTPClient( { detail_url: """

Сведения о заказчике

Полное наименование
ФЕДЕРАЛЬНОЕ ГБУ НАУКИ
ИНН / КПП
4101020011 / 410101001
ОГРН
1024101023456
""".encode() } ) records = client.fetch_records( content=f"""
№ 0338100002026000022
Работа комиссии
Объект закупки
Поставка оборудования
Заказчик
ФЕДЕРАЛЬНОЕ ГБУ НАУКИ
Начальная цена
1 000,00 ₽
Размещено
19.05.2026
""".encode(), file_name="results.html", ) self.assertEqual(len(records), 1) record = records[0] self.assertEqual(record.inn, "4101020011") self.assertEqual(record.ogrn, "1024101023456") self.assertEqual(record.payload["kpp"], "410101001") self.assertEqual(record.payload["detail_url"], detail_url) self.assertEqual(client._http_client.downloaded_urls, [detail_url]) def test_procurement_card_keeps_record_when_detail_page_is_unavailable(self): detail_url = ( "https://zakupki.gov.ru/epz/order/notice/ea20/view/" "common-info.html?regNumber=0338100002026000022" ) client = StructuredDataClient(source="procurements_44fz") client._http_client = _FakeHTTPClient( {detail_url: HTTPClientError("detail unavailable", url=detail_url)} ) records = client.fetch_records( content=f"""
№ 0338100002026000022
Объект закупки
Поставка оборудования
Заказчик
ФЕДЕРАЛЬНОЕ ГБУ НАУКИ
""".encode(), file_name="results.html", ) self.assertEqual(len(records), 1) self.assertEqual(records[0].inn, "") self.assertEqual(records[0].ogrn, "") self.assertEqual(records[0].organisation_name, "ФЕДЕРАЛЬНОЕ ГБУ НАУКИ") def test_procurement_card_prefers_organization_page_for_identity(self): detail_url = ( "https://zakupki.gov.ru/epz/order/notice/zk20/view/" "common-info.html?regNumber=0322300001726000667" ) identity_url = ( "https://zakupki.gov.ru/epz/organization/view/" "info.html?organizationCode=03223000017" ) client = StructuredDataClient(source="procurements_44fz") client._http_client = _FakeHTTPClient( { identity_url: """
Заказчик
21.07.2016
ОГРН
1022701405737
ИНН
2725006476
КПП
272501001
Полное наименование
КГБУЗ БОЛЬНИЦА
""".encode() } ) records = client.fetch_records( content=f"""
44-ФЗ
№ 0322300001726000667
Объект закупки
Поставка оборудования
Заказчик
КГБУЗ БОЛЬНИЦА
КГБУЗ БОЛЬНИЦА
""".encode(), file_name="results.html", ) self.assertEqual(records[0].url, detail_url) self.assertEqual(records[0].inn, "2725006476") self.assertEqual(records[0].ogrn, "1022701405737") self.assertEqual(records[0].organisation_name, "КГБУЗ БОЛЬНИЦА") self.assertEqual(client._http_client.downloaded_urls, [identity_url]) def test_procurement_card_rejects_untrusted_detail_urls(self): loopback_identity_url = ( "http://127.0.0.1/epz/organization/view/" "info.html?inn=2725006476" ) foreign_detail_url = ( "https://example.test/epz/order/notice/zk20/view/" "common-info.html?regNumber=0322300001726000667" ) client = StructuredDataClient(source="procurements_44fz") client._http_client = _FakeHTTPClient( { loopback_identity_url: b"", foreign_detail_url: b"", } ) records = client.fetch_records( content=f"""
44-ФЗ
№ 0322300001726000667
Объект закупки
Поставка оборудования
Заказчик
КГБУЗ БОЛЬНИЦА
КГБУЗ БОЛЬНИЦА
""".encode(), file_name="results.html", ) self.assertNotIn("detail_url", records[0].payload) self.assertNotIn("identity_url", records[0].payload) self.assertEqual(client._http_client.downloaded_urls, []) def test_procurement_card_resolves_relative_official_urls(self): detail_href = ( "/epz/order/notice/zk20/view/" "common-info.html?regNumber=0322300001726000667" ) identity_href = "/epz/organization/view/info.html?organizationCode=03223000017" client = StructuredDataClient( source="procurements_44fz", enrich_eis_detail_pages=False, ) records = client.fetch_records( content=f"""
44-ФЗ
№ 0322300001726000667
Объект закупки
Поставка оборудования
Заказчик
КГБУЗ БОЛЬНИЦА
КГБУЗ БОЛЬНИЦА
""".encode(), file_name="results.html", ) self.assertEqual( records[0].payload["detail_url"], f"https://zakupki.gov.ru{detail_href}", ) self.assertEqual( records[0].payload["identity_url"], f"https://zakupki.gov.ru{identity_href}", ) class StructuredDataClientEisCardParsingTest(SimpleTestCase): def test_contract_card_prefers_contract_details_over_order_notice(self): contract_url = ( "https://zakupki.gov.ru/epz/contract/contractCard/" "common-info.html?reestrNumber=3310300251025000007" ) notice_url = ( "https://zakupki.gov.ru/epz/order/notice/view/" "common-info.html?regNumber=0126300014725000080" ) client = StructuredDataClient( source="contracts", enrich_eis_detail_pages=False, ) records = client.fetch_records( content=f"""
№ 3310300251025000007
Заказчик
МБДОУ СКАЗКА
Объекты закупки
Мясо птицы
Размещен контракт в реестре контрактов
04.12.2025
Сведения закупки
""".encode(), file_name="results.html", ) self.assertEqual(records[0].url, contract_url) self.assertEqual(records[0].organisation_name, "МБДОУ СКАЗКА") self.assertEqual(records[0].record_date, "04.12.2025") def test_unfair_supplier_skips_empty_placed_label(self): client = StructuredDataClient( source="unfair_suppliers", enrich_eis_detail_pages=False, ) records = client.fetch_records( content="""
44-ФЗ
№ 26007353
Размещено
Наименование (ФИО) недобросовестного поставщика
ООО ПРОГРЕСС
ИНН (аналог ИНН)
9728104322
Включено
14.07.2026
""".encode(), file_name="results.html", ) self.assertEqual(records[0].title, "ООО ПРОГРЕСС") self.assertEqual(records[0].organisation_name, "ООО ПРОГРЕСС") self.assertEqual(records[0].record_date, "14.07.2026")