"""Tests for external data endpoints.""" from __future__ import annotations from datetime import date from apps.external_data.models import ElectronicDocumentExchangeEntry, MediaMention from django.test import override_settings from rest_framework import status from rest_framework.test import APITestCase from tests.apps.external_data.factories import ( ArbitrationCaseFactory, BankruptcyProcedureFactory, DefenseUnreliableSupplierFactory, FinancialReportFactory, FinancialReportLineFactory, IndustrialCertificateFactory, IndustrialProductFactory, InformationSecurityRegistryEntryFactory, LaborVacancyFactory, ManufacturerRegistryEntryFactory, ProsecutorCheckFactory, PublicProcurementFactory, ) from tests.apps.organization.factories import OrganizationFactory from tests.apps.user.factories import UserFactory @override_settings(ROOT_URLCONF="core.urls") class ExternalDataApiTest(APITestCase): def setUp(self): self.user = UserFactory.create_user() self.client.force_authenticate(self.user) self.organization = OrganizationFactory.create() self.other_organization = OrganizationFactory.create() def test_industrial_products_endpoint_uses_classic_pagination(self): IndustrialProductFactory.create( organization=self.organization, product_name="Лазерные датчики расстояния", ) IndustrialProductFactory.create(organization=self.other_organization) response = self.client.get( f"/api/v1/industrial-products/?organization={self.organization.id}&search=датчики" ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIn("results", response.data) self.assertEqual(response.data["count"], 1) self.assertEqual( response.data["results"][0]["organization"], str(self.organization.id) ) def test_manufacturing_source_endpoints_are_exposed(self): IndustrialCertificateFactory.create( organization=self.organization, certificate_number="CERT-001", issue_date=date(2026, 1, 10), ) ManufacturerRegistryEntryFactory.create( organization=self.organization, full_legal_name="АО Альфа", ) IndustrialCertificateFactory.create(organization=self.other_organization) ManufacturerRegistryEntryFactory.create(organization=self.other_organization) certificates_response = self.client.get( f"/api/v1/industrial-certificates/?organization={self.organization.id}" "&issue_date_from=2026-01-01&issue_date_to=2026-12-31" ) manufacturers_response = self.client.get( f"/api/v1/manufacturers/?organization={self.organization.id}" "&search=Альфа" ) self.assertEqual(certificates_response.status_code, status.HTTP_200_OK) self.assertEqual(manufacturers_response.status_code, status.HTTP_200_OK) self.assertEqual(certificates_response.data["count"], 1) self.assertEqual(manufacturers_response.data["count"], 1) def test_prosecutor_checks_support_date_range_filters(self): ProsecutorCheckFactory.create( organization=self.organization, law_type="294_fz", start_date=date(2025, 1, 15), ) ProsecutorCheckFactory.create( organization=self.organization, law_type="294_fz", start_date=date(2023, 1, 15), ) response = self.client.get( f"/api/v1/prosecutor-checks/?organization={self.organization.id}" "&law_type=294_fz&start_date_from=2024-01-01&start_date_to=2025-12-31" ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["count"], 1) def test_public_procurements_and_arbitration_cases_filters(self): PublicProcurementFactory.create( organization=self.organization, law_type="44_fz", contract_date=date(2025, 1, 15), ) ArbitrationCaseFactory.create( organization=self.organization, party_role="defendant", decision_date=date(2026, 1, 27), ) procurement_response = self.client.get( f"/api/v1/public-procurements/?organization={self.organization.id}" "&law_type=44_fz&contract_date_from=2024-01-01&contract_date_to=2025-12-31" ) arbitration_response = self.client.get( f"/api/v1/arbitration-cases/?organization={self.organization.id}" "&party_role=defendant&decision_date_from=2025-01-01&decision_date_to=2026-12-31" ) self.assertEqual(procurement_response.status_code, status.HTTP_200_OK) self.assertEqual(procurement_response.data["count"], 1) self.assertEqual(arbitration_response.status_code, status.HTTP_200_OK) self.assertEqual(arbitration_response.data["count"], 1) self.assertIn("claim_amount", arbitration_response.data["results"][0]) def test_corporation_memberships_filter(self): InformationSecurityRegistryEntryFactory( organization=self.organization, presence_status="present", ) InformationSecurityRegistryEntryFactory( organization=self.other_organization, presence_status="absent", ) response = self.client.get( f"/api/v1/corporation-memberships/?organization={self.organization.id}" "&presence_status=present" ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["count"], 1) result = response.data["results"][0] self.assertEqual( result["organization"], str(self.organization.id), ) self.assertEqual(result["presence_status"], "present") self.assertIn("registry_name", result) self.assertIn("entry_number", result) def test_additional_exchange_sections_are_exposed(self): BankruptcyProcedureFactory.create( organization=self.organization, message_type="Сообщение о намерении", message_date=date(2026, 3, 26), ) DefenseUnreliableSupplierFactory.create( organization=self.organization, registry_source="fas_goz", included_at=date(2026, 2, 20), ) LaborVacancyFactory.create( organization=self.organization, vacancy_source="trudvsem", published_at=date(2026, 4, 1), ) BankruptcyProcedureFactory.create(organization=self.other_organization) DefenseUnreliableSupplierFactory.create(organization=self.other_organization) LaborVacancyFactory.create(organization=self.other_organization) bankruptcy_response = self.client.get( f"/api/v1/bankruptcy-procedures/?organization={self.organization.id}" "&message_date_from=2026-01-01&message_date_to=2026-12-31" ) defense_response = self.client.get( f"/api/v1/defense-unreliable-suppliers/?organization={self.organization.id}" "®istry_source=fas_goz" ) vacancies_response = self.client.get( f"/api/v1/labor-vacancies/?organization={self.organization.id}" "&vacancy_source=trudvsem" ) self.assertEqual(bankruptcy_response.status_code, status.HTTP_200_OK) self.assertEqual(defense_response.status_code, status.HTTP_200_OK) self.assertEqual(vacancies_response.status_code, status.HTTP_200_OK) self.assertEqual(bankruptcy_response.data["count"], 1) self.assertEqual(defense_response.data["count"], 1) self.assertEqual(vacancies_response.data["count"], 1) self.assertEqual( vacancies_response.data["results"][0]["title"], "Инженер-испытатель", ) def test_financial_reports_endpoint_returns_lines(self): report = FinancialReportFactory.create( organization=self.organization, status="success", ) FinancialReportLineFactory.create(report=report, line_code="1600") FinancialReportFactory.create(organization=self.other_organization) response = self.client.get( f"/api/v1/financial-reports/?organization={self.organization.id}" "&status=success" ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data["count"], 1) self.assertEqual(response.data["results"][0]["lines"][0]["line_code"], "1600") def test_gosedo_and_media_endpoints_filter_and_separate_full_text(self): ElectronicDocumentExchangeEntry.objects.create( organization=self.organization, external_id="gosedo-1", record_type="participant", title="АО Тест", status="active", attestation_status="attested", source_version="633", source_published_at=date(2026, 8, 10), ) mention = MediaMention.objects.create( organization=self.organization, external_id="a" * 64, news_source="Тестовое СМИ", title="Заголовок", sentiment="positive", published_at=date(2026, 7, 1), excerpt_lines=["1", "2", "3", "4"], full_text="1\n2\n3\n4\n5", ) gosedo_response = self.client.get( f"/api/v1/electronic-document-exchange/?organization={self.organization.id}" "&record_type=participant&attestation_status=attested&source_version=633" "&source_published_at_from=2026-08-01&source_published_at_to=2026-08-31" ) media_list_response = self.client.get( f"/api/v1/media-mentions/?organization={self.organization.id}" "&source=Тестовое СМИ&sentiment=positive" ) media_detail_response = self.client.get(f"/api/v1/media-mentions/{mention.id}/") self.assertEqual(gosedo_response.status_code, status.HTTP_200_OK) self.assertEqual(gosedo_response.data["count"], 1) self.assertEqual(media_list_response.status_code, status.HTTP_200_OK) self.assertNotIn("full_text", media_list_response.data["results"][0]) self.assertEqual( media_list_response.data["results"][0]["excerpt_lines"], ["1", "2", "3", "4"], ) self.assertEqual(media_detail_response.status_code, status.HTTP_200_OK) self.assertEqual(media_detail_response.data["full_text"], "1\n2\n3\n4\n5")