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")