Files
mostovik-backend/tests/apps/organizations/test_api_v2.py
Aleksandr Meshchriakov 0f17ff6773
All checks were successful
CI/CD Pipeline / Quality Gate (push) Successful in 26s
CI/CD Pipeline / Build and Push Images (push) Successful in 6s
CI/CD Pipeline / Internal Notify (push) Successful in 0s
CI/CD Pipeline / Deploy Dev in Dokploy (push) Successful in 1s
Add organizations v2 API and registry enrichment
2026-05-06 19:04:46 +02:00

922 lines
34 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Tests for organizations API v2."""
from apps.parsers.models import (
FinancialReport,
FinancialReportLine,
GenericParserRecord,
ParserLoadLog,
)
from django.core.cache import cache
from django.db import connection
from django.test import override_settings
from django.test.utils import CaptureQueriesContext
from django.urls import reverse
from organizations.models import Organization
from organizations.services import OrganizationDataSnapshotRefreshService
from rest_framework import status
from rest_framework.test import APITestCase
from tests.apps.parsers.factories import (
IndustrialCertificateRecordFactory,
IndustrialProductRecordFactory,
InspectionRecordFactory,
ManufacturerRecordFactory,
ProcurementRecordFactory,
)
from tests.apps.registers.factories import (
OrganizationFactory as RegistryOrganizationFactory,
)
from tests.apps.registers.factories import (
RegisterFactory,
RegistryMembershipPeriodFactory,
)
from tests.apps.user.factories import UserFactory
class OrganizationsApiV2Test(APITestCase):
"""Checks v2 canonical organizations endpoints."""
def setUp(self):
cache.clear()
self.user = UserFactory.create_user()
self.client.force_authenticate(self.user)
def test_list_is_paginated_and_available_only_under_v2(self):
Organization.objects.create(
name='ООО "Альфа"',
inn="7707083893",
kpp="770701001",
ogrn="1027700132195",
)
Organization.objects.create(
name="ИП Иванов Иван Иванович",
inn="500100732259",
ogrip="304500116000157",
)
response = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"page_size": 1, "has_registry": "false"},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["success"], True)
self.assertEqual(len(response.data["data"]), 1)
self.assertEqual(response.data["meta"]["pagination"]["total_count"], 2)
self.assertEqual(response.data["meta"]["pagination"]["page_size"], 1)
v1_response = self.client.get("/api/v1/organizations/")
self.assertEqual(v1_response.status_code, status.HTTP_404_NOT_FOUND)
def test_openapi_documents_v2_organizations_endpoints(self):
response = self.client.get(
reverse("schema-swagger-ui"),
{"format": "openapi"},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
paths = response.data["paths"]
list_operation = paths["/api/v2/organizations/"]["get"]
detail_operation = paths["/api/v2/organizations/{uid}/"]["get"]
self.assertEqual(list_operation["tags"], ["Организации"])
self.assertEqual(detail_operation["tags"], ["Организации"])
self.assertEqual(
list_operation["operationId"],
"v2_organizations_list",
)
self.assertEqual(
detail_operation["operationId"],
"v2_organizations_retrieve",
)
list_parameters = {
parameter["name"]: parameter for parameter in list_operation["parameters"]
}
for expected_name in (
"page",
"page_size",
"search",
"ordering",
"registry",
"has_registry",
"has_fns_reports",
"data",
"exclude_data",
):
self.assertIn(expected_name, list_parameters)
self.assertIn("по умолчанию true", list_parameters["has_registry"]["description"])
self.assertIn(
"industrial_products",
list_parameters["data"]["description"],
)
detail_parameters = {
parameter["name"]: parameter
for parameter in detail_operation["parameters"]
}
self.assertEqual(detail_parameters["uid"]["type"], "string")
self.assertEqual(detail_parameters["uid"]["format"], "uuid")
self.assertIn("data", detail_parameters)
self.assertIn("exclude_data", detail_parameters)
self.assertIn("Пагинированный", list_operation["responses"]["200"]["description"])
self.assertIn(
"Карточка организации",
detail_operation["responses"]["200"]["description"],
)
def test_retrieve_returns_item_by_uid(self):
organization = Organization.objects.create(
name='ООО "Ромашка"',
inn="7712345678",
kpp="771201001",
ogrn="1027700132196",
)
response = self.client.get(
reverse("api_v2:organizations:organizations-detail", args=[organization.uid])
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["uid"], str(organization.uid))
self.assertEqual(response.data["name"], 'ООО "Ромашка"')
def test_response_includes_normalized_name(self):
organization = Organization.objects.create(
name='АКЦИОНЕРНОЕ ОБЩЕСТВО "СЕВЕРНЫЙ МОСТ"',
inn="7712345679",
kpp="771201002",
ogrn="1027700132197",
)
response = self.client.get(
reverse("api_v2:organizations:organizations-detail", args=[organization.uid])
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["name"], 'АКЦИОНЕРНОЕ ОБЩЕСТВО "СЕВЕРНЫЙ МОСТ"')
self.assertEqual(response.data["normalized_name"], 'АО "Северный Мост"')
def test_list_keeps_data_source_summary_when_data_payload_is_excluded(self):
organization = Organization.objects.create(
name='ООО "Сводка данных"',
inn="7712345681",
kpp="771201004",
ogrn="1027700132199",
)
IndustrialCertificateRecordFactory(
inn=organization.inn,
ogrn=organization.ogrn,
)
OrganizationDataSnapshotRefreshService.refresh(
organization_uids=[str(organization.uid)]
)
response = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{
"inn": organization.inn,
"has_registry": "false",
"exclude_data": (
"industrial,industrial_products,manufactures,inspections,"
"procurements,procurements_44fz,procurements_223fz,contracts,"
"unfair_suppliers,fas_goz,arbitration,fedresurs_bankruptcy,"
"fstec,vacancies,fns_reports"
),
},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
item = response.data["data"][0]
self.assertEqual(item["data"], {})
self.assertEqual(
item["data_sources"],
[{"source": "industrial", "count": 1}],
)
def test_normalized_name_compacts_scientific_production_forms(self):
organization = Organization.objects.create(
name='Научно-Производственное Предприятие "ИМПУЛЬС"',
inn="7712345680",
kpp="771201003",
ogrn="1027700132198",
)
response = self.client.get(
reverse("api_v2:organizations:organizations-detail", args=[organization.uid])
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["normalized_name"], 'НПП "Импульс"')
def test_list_filters_by_identifiers_and_searches_by_name(self):
target = Organization.objects.create(
name='ООО "Северный мост"',
inn="7711111111",
kpp="771101001",
ogrn="1027700132111",
)
Organization.objects.create(
name='АО "Южный путь"',
inn="7722222222",
kpp="772201001",
ogrn="1027700132222",
)
by_inn = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"inn": target.inn, "has_registry": "false"},
)
by_search = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"search": "мост", "has_registry": "false"},
)
self.assertEqual(by_inn.status_code, status.HTTP_200_OK)
self.assertEqual(by_inn.data["meta"]["pagination"]["total_count"], 1)
self.assertEqual(by_inn.data["data"][0]["uid"], str(target.uid))
self.assertEqual(by_search.status_code, status.HTTP_200_OK)
self.assertEqual(by_search.data["meta"]["pagination"]["total_count"], 1)
self.assertEqual(by_search.data["data"][0]["uid"], str(target.uid))
def test_list_searches_by_identifier_fragments_for_dashboard(self):
target = Organization.objects.create(
name='ООО "Поиск по реквизитам"',
inn="7711111122",
kpp="771102222",
ogrn="1027700132122",
)
Organization.objects.create(
name='ООО "Другая организация"',
inn="7722222233",
kpp="772203333",
ogrn="1027700132233",
)
url = reverse("api_v2:organizations:organizations-list")
for search_value in ("111122", "1027700132122", "102222"):
with self.subTest(search_value=search_value):
response = self.client.get(
url,
{"search": search_value, "has_registry": "false"},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["meta"]["pagination"]["total_count"], 1)
self.assertEqual(response.data["data"][0]["uid"], str(target.uid))
def test_list_response_is_cached_by_query_string(self):
Organization.objects.create(
name='ООО "Кеш"',
inn="7733333333",
kpp="773301001",
ogrn="1027700132333",
)
url = reverse("api_v2:organizations:organizations-list")
first_response = self.client.get(
url,
{"inn": "7733333333", "has_registry": "false"},
)
Organization.objects.create(
name='ООО "После кеша"',
inn="7744444444",
kpp="774401001",
ogrn="1027700132444",
)
second_response = self.client.get(
url,
{"inn": "7733333333", "has_registry": "false"},
)
different_query_response = self.client.get(
url,
{"inn": "7744444444", "has_registry": "false"},
)
self.assertEqual(first_response.status_code, status.HTTP_200_OK)
self.assertEqual(first_response["X-Cache"], "MISS")
self.assertEqual(second_response["X-Cache"], "HIT")
self.assertEqual(second_response.data, first_response.data)
self.assertEqual(different_query_response["X-Cache"], "MISS")
self.assertEqual(different_query_response.data["data"][0]["inn"], "7744444444")
def test_retrieve_response_is_cached(self):
organization = Organization.objects.create(
name='ООО "Деталь"',
inn="7755555555",
kpp="775501001",
ogrn="1027700132555",
)
url = reverse("api_v2:organizations:organizations-detail", args=[organization.uid])
first_response = self.client.get(url)
organization.name = 'ООО "Изменено"'
organization.save(update_fields=["name"])
second_response = self.client.get(url)
self.assertEqual(first_response.status_code, status.HTTP_200_OK)
self.assertEqual(first_response["X-Cache"], "MISS")
self.assertEqual(second_response["X-Cache"], "HIT")
self.assertEqual(second_response.data["name"], 'ООО "Деталь"')
def test_list_includes_parser_presence_and_active_registries(self):
organization = Organization.objects.create(
name='ООО "Данные"',
inn="7777777777",
kpp="777701001",
ogrn="1027700132777",
)
registry = RegisterFactory(name="Росатом ГОЗ")
registry_organization = RegistryOrganizationFactory(
mn_inn=int(organization.inn),
mn_ogrn=int(organization.ogrn),
)
RegistryMembershipPeriodFactory(
registry=registry,
organization=registry_organization,
)
certificate = IndustrialCertificateRecordFactory(
inn=organization.inn,
ogrn=organization.ogrn,
certificate_number="CERT-ORG-V2-1",
)
product = IndustrialProductRecordFactory(
inn=organization.inn,
ogrn=organization.ogrn,
registry_number="PRODUCT-ORG-V2-1",
)
manufacturer = ManufacturerRecordFactory(
inn=organization.inn,
ogrn=organization.ogrn,
full_legal_name='ООО "Данные"',
)
inspection = InspectionRecordFactory(
inn=organization.inn,
ogrn=organization.ogrn,
registration_number="INSPECTION-ORG-V2-1",
)
procurement = ProcurementRecordFactory(
customer_inn=organization.inn,
customer_ogrn=organization.ogrn,
purchase_number="PROCUREMENT-ORG-V2-1",
)
generic_record = GenericParserRecord.objects.create(
load_batch=1,
source=ParserLoadLog.Source.FSTEC,
external_id="fstec-1",
inn=organization.inn,
ogrn=organization.ogrn,
organisation_name=organization.name,
title="FSTEC record",
payload={"source": "fstec"},
)
GenericParserRecord.objects.create(
load_batch=1,
source=ParserLoadLog.Source.PROCUREMENTS_44FZ,
external_id="procurements-44fz-1",
inn=organization.inn,
ogrn=organization.ogrn,
organisation_name=organization.name,
title="44-FZ record",
)
financial_report = FinancialReport.objects.create(
external_id="fin-1",
ogrn=organization.ogrn,
file_name="fin.xlsx",
file_hash="a" * 64,
load_batch=1,
status=FinancialReport.Status.SUCCESS,
source=FinancialReport.SourceType.API,
)
FinancialReportLine.objects.create(
report=financial_report,
form_code="1",
line_code="1100",
line_name="Внеоборотные активы",
year=2021,
period_start=100,
period_end=200,
)
FinancialReportLine.objects.create(
report=financial_report,
form_code="1",
line_code="1300",
line_name="Капитал и резервы",
year=2021,
period_start=300,
period_end=400,
)
FinancialReportLine.objects.create(
report=financial_report,
form_code="2",
line_code="2110",
line_name="Выручка",
year=2022,
period_start=None,
period_end=500,
)
response = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"inn": organization.inn},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
item = response.data["data"][0]
self.assertEqual(
item["registries"],
[{"id": str(registry.id), "name": "Росатом ГОЗ"}],
)
self.assertNotIn("data_presence", item)
self.assertIn("data", item)
self.assertEqual(
item["data"]["industrial"],
[
{
"id": certificate.id,
"load_batch": certificate.load_batch,
"issue_date": certificate.issue_date,
"issue_date_normalized": None,
"certificate_number": "CERT-ORG-V2-1",
"expiry_date": certificate.expiry_date,
"expiry_date_normalized": None,
"certificate_file_url": certificate.certificate_file_url,
"organisation_name": certificate.organisation_name,
"inn": organization.inn,
"ogrn": organization.ogrn,
"registry_organization": None,
"created_at": certificate.created_at.isoformat().replace(
"+00:00", "Z"
),
"updated_at": certificate.updated_at.isoformat().replace(
"+00:00", "Z"
),
}
],
)
self.assertEqual(
item["data"]["industrial_products"][0]["registry_number"],
"PRODUCT-ORG-V2-1",
)
self.assertEqual(
item["data"]["industrial_products"][0]["id"],
product.id,
)
self.assertEqual(
item["data"]["manufactures"][0]["id"],
manufacturer.id,
)
self.assertEqual(
item["data"]["inspections"][0]["registration_number"],
"INSPECTION-ORG-V2-1",
)
self.assertEqual(
item["data"]["inspections"][0]["id"],
inspection.id,
)
self.assertEqual(
item["data"]["procurements"][0]["purchase_number"],
"PROCUREMENT-ORG-V2-1",
)
self.assertEqual(
item["data"]["procurements"][0]["id"],
procurement.id,
)
self.assertEqual(
item["data"]["procurements_44fz"][0]["external_id"],
"procurements-44fz-1",
)
self.assertEqual(
item["data"]["fstec"][0]["id"],
generic_record.id,
)
self.assertEqual(
item["data"]["fns_reports"][0]["external_id"],
"fin-1",
)
self.assertEqual(
item["data"]["fns_reports"][0]["id"],
financial_report.id,
)
self.assertEqual(item["data"]["fns_reports"][0]["lines_count"], 3)
self.assertEqual(
item["data"]["fns_reports"][0]["lines"]["2021"]["active"]["1100"],
{
"form_code": "1",
"name": "Внеоборотные активы",
"period_start": 100,
"period_end": 200,
},
)
self.assertEqual(
item["data"]["fns_reports"][0]["lines"]["2021"]["passive"]["1300"],
{
"form_code": "1",
"name": "Капитал и резервы",
"period_start": 300,
"period_end": 400,
},
)
self.assertEqual(
item["data"]["fns_reports"][0]["lines"]["2022"]["form_2"]["2110"],
{
"form_code": "2",
"name": "Выручка",
"period_start": None,
"period_end": 500,
},
)
self.assertTrue(
all(isinstance(value, list) for value in item["data"].values())
)
def test_filters_by_registry_and_has_registry(self):
with_registry = Organization.objects.create(
name='ООО "В реестре"',
inn="7788888888",
kpp="778801001",
ogrn="1027700132888",
)
without_registry = Organization.objects.create(
name='ООО "Без реестра"',
inn="7799999999",
kpp="779901001",
ogrn="1027700132999",
)
registry = RegisterFactory(name="Роскосмос ОПК")
registry_organization = RegistryOrganizationFactory(
mn_inn=int(with_registry.inn),
mn_ogrn=int(with_registry.ogrn),
)
RegistryMembershipPeriodFactory(
registry=registry,
organization=registry_organization,
)
by_registry = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"registry": str(registry.id)},
)
has_registry = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"has_registry": "true"},
)
no_registry = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"has_registry": "false", "ordering": "inn"},
)
self.assertEqual(by_registry.status_code, status.HTTP_200_OK)
self.assertEqual(by_registry.data["meta"]["pagination"]["total_count"], 1)
self.assertEqual(by_registry.data["data"][0]["uid"], str(with_registry.uid))
self.assertEqual(has_registry.data["meta"]["pagination"]["total_count"], 1)
self.assertEqual(has_registry.data["data"][0]["uid"], str(with_registry.uid))
self.assertEqual(no_registry.data["meta"]["pagination"]["total_count"], 1)
self.assertEqual(no_registry.data["data"][0]["uid"], str(without_registry.uid))
def test_list_defaults_to_has_registry_true(self):
with_registry = Organization.objects.create(
name='ООО "Дефолтный реестр"',
inn="7800000101",
kpp="780001101",
ogrn="1027700133101",
)
Organization.objects.create(
name='ООО "Скрыто по дефолту"',
inn="7800000102",
kpp="780001102",
ogrn="1027700133102",
)
registry = RegisterFactory(name="Дефолтный реестр")
registry_organization = RegistryOrganizationFactory(
mn_inn=int(with_registry.inn),
mn_ogrn=int(with_registry.ogrn),
)
RegistryMembershipPeriodFactory(
registry=registry,
organization=registry_organization,
)
default_response = self.client.get(
reverse("api_v2:organizations:organizations-list")
)
explicit_false_response = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"has_registry": "false"},
)
self.assertEqual(default_response.status_code, status.HTTP_200_OK)
self.assertEqual(default_response.data["meta"]["pagination"]["total_count"], 1)
self.assertEqual(default_response.data["data"][0]["uid"], str(with_registry.uid))
self.assertEqual(
explicit_false_response.data["meta"]["pagination"]["total_count"],
1,
)
self.assertEqual(
explicit_false_response.data["data"][0]["inn"],
"7800000102",
)
def test_filters_by_data_presence(self):
with_industrial = Organization.objects.create(
name='ООО "С промышленностью"',
inn="7800000001",
kpp="780001001",
ogrn="1027700133001",
)
with_fns = Organization.objects.create(
name='ООО "С отчетностью"',
inn="7800000002",
kpp="780001002",
ogrn="1027700133002",
)
without_data = Organization.objects.create(
name='ООО "Без данных"',
inn="7800000003",
kpp="780001003",
ogrn="1027700133003",
)
IndustrialCertificateRecordFactory(
inn=with_industrial.inn,
ogrn=with_industrial.ogrn,
)
FinancialReport.objects.create(
external_id="fin-presence-1",
ogrn=with_fns.ogrn,
file_name="fin_presence.xlsx",
file_hash="b" * 64,
load_batch=1,
status=FinancialReport.Status.SUCCESS,
source=FinancialReport.SourceType.API,
)
has_industrial = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"has_industrial": "true", "has_registry": "false"},
)
no_industrial = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{
"has_industrial": "false",
"has_registry": "false",
"ordering": "inn",
},
)
has_fns = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"has_fns_reports": "true", "has_registry": "false"},
)
self.assertEqual(has_industrial.status_code, status.HTTP_200_OK)
self.assertEqual(has_industrial.data["meta"]["pagination"]["total_count"], 1)
self.assertEqual(
has_industrial.data["data"][0]["uid"],
str(with_industrial.uid),
)
self.assertEqual(no_industrial.data["meta"]["pagination"]["total_count"], 2)
self.assertEqual(
[item["uid"] for item in no_industrial.data["data"]],
[str(with_fns.uid), str(without_data.uid)],
)
self.assertEqual(has_fns.data["meta"]["pagination"]["total_count"], 1)
self.assertEqual(has_fns.data["data"][0]["uid"], str(with_fns.uid))
def test_limits_response_data_sources(self):
organization = Organization.objects.create(
name='ООО "Источник"',
inn="7800000201",
kpp="780002101",
ogrn="1027700133201",
)
IndustrialCertificateRecordFactory(
inn=organization.inn,
ogrn=organization.ogrn,
)
GenericParserRecord.objects.create(
load_batch=1,
source=ParserLoadLog.Source.FSTEC,
external_id="fstec-source-limit",
inn=organization.inn,
ogrn=organization.ogrn,
organisation_name=organization.name,
)
FinancialReport.objects.create(
external_id="fin-source-limit",
ogrn=organization.ogrn,
file_name="fin_source_limit.xlsx",
file_hash="c" * 64,
load_batch=1,
status=FinancialReport.Status.SUCCESS,
source=FinancialReport.SourceType.API,
)
detail_url = reverse(
"api_v2:organizations:organizations-detail",
args=[organization.uid],
)
only_response = self.client.get(
detail_url,
{"data": "industrial,fns_reports"},
)
excluded_response = self.client.get(
detail_url,
{"exclude_data": "fns_reports"},
)
repeated_response = self.client.get(
detail_url,
[("data", "industrial"), ("data", "fstec")],
)
empty_response = self.client.get(
detail_url,
{"data": "industrial", "exclude_data": "industrial"},
)
self.assertEqual(only_response.status_code, status.HTTP_200_OK)
self.assertEqual(
set(only_response.data["data"]),
{"industrial", "fns_reports"},
)
self.assertEqual(len(only_response.data["data"]["industrial"]), 1)
self.assertEqual(len(only_response.data["data"]["fns_reports"]), 1)
self.assertEqual(excluded_response.status_code, status.HTTP_200_OK)
self.assertNotIn("fns_reports", excluded_response.data["data"])
self.assertIn("industrial", excluded_response.data["data"])
self.assertEqual(repeated_response.status_code, status.HTTP_200_OK)
self.assertEqual(
set(repeated_response.data["data"]),
{"industrial", "fstec"},
)
self.assertEqual(empty_response.status_code, status.HTTP_200_OK)
self.assertEqual(empty_response.data["data"], {})
def test_rejects_unknown_response_data_source(self):
organization = Organization.objects.create(
name='ООО "Неверный источник"',
inn="7800000202",
kpp="780002102",
ogrn="1027700133202",
)
response = self.client.get(
reverse("api_v2:organizations:organizations-detail", args=[organization.uid]),
{"data": "unknown"},
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertIn("data", response.data)
def test_selected_data_sources_keep_constant_query_count(self):
organization = Organization.objects.create(
name='ООО "Без N+1"',
inn="7800000203",
kpp="780002103",
ogrn="1027700133203",
)
IndustrialCertificateRecordFactory(
inn=organization.inn,
ogrn=organization.ogrn,
)
for index, year in enumerate((2021, 2022, 2023, 2024), start=1):
report = FinancialReport.objects.create(
external_id=f"fin-query-count-{year}",
ogrn=organization.ogrn,
file_name=f"fin_query_count_{year}.xlsx",
file_hash=f"{index}" * 64,
load_batch=1,
status=FinancialReport.Status.SUCCESS,
source=FinancialReport.SourceType.API,
)
FinancialReportLine.objects.bulk_create(
[
FinancialReportLine(
report=report,
form_code="1",
line_code=str(1100 + line_index),
line_name=f"Line {line_index}",
year=year,
period_start=line_index,
period_end=line_index * 2,
)
for line_index in range(1, 101)
]
)
for source in (
ParserLoadLog.Source.FSTEC,
ParserLoadLog.Source.CONTRACTS,
ParserLoadLog.Source.TRUDVSEM,
):
GenericParserRecord.objects.create(
load_batch=1,
source=source,
external_id=f"{source}-query-count",
inn=organization.inn,
ogrn=organization.ogrn,
organisation_name=organization.name,
)
OrganizationDataSnapshotRefreshService.refresh(
organization_uids=[str(organization.uid)],
)
url = reverse("api_v2:organizations:organizations-detail", args=[organization.uid])
with CaptureQueriesContext(connection) as captured:
response = self.client.get(
url,
{"data": "industrial,fns_reports,fstec,contracts,vacancies"},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
set(response.data["data"]),
{"industrial", "fns_reports", "fstec", "contracts", "vacancies"},
)
self.assertNotIn("trudvsem", response.data["data"])
self.assertEqual(len(response.data["data"]["fns_reports"]), 4)
self.assertLessEqual(len(captured), 1)
def test_v2_renames_trudvsem_data_source_to_vacancies(self):
organization = Organization.objects.create(
name='ООО "Вакансии"',
inn="7800000204",
kpp="780002104",
ogrn="1027700133204",
)
GenericParserRecord.objects.create(
load_batch=1,
source=ParserLoadLog.Source.TRUDVSEM,
external_id="vacancy-1",
inn=organization.inn,
ogrn=organization.ogrn,
organisation_name=organization.name,
title="Инженер",
)
OrganizationDataSnapshotRefreshService.refresh(
organization_uids=[str(organization.uid)],
)
detail_url = reverse(
"api_v2:organizations:organizations-detail",
args=[organization.uid],
)
vacancies_response = self.client.get(detail_url, {"data": "vacancies"})
internal_source_response = self.client.get(detail_url, {"data": "trudvsem"})
has_vacancies_response = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{
"has_vacancies": "true",
"has_registry": "false",
"data": "vacancies",
},
)
self.assertEqual(vacancies_response.status_code, status.HTTP_200_OK)
self.assertEqual(set(vacancies_response.data["data"]), {"vacancies"})
self.assertEqual(
vacancies_response.data["data"]["vacancies"][0]["external_id"],
"vacancy-1",
)
self.assertNotIn("trudvsem", vacancies_response.data["data"])
self.assertEqual(
internal_source_response.status_code,
status.HTTP_400_BAD_REQUEST,
)
self.assertIn("trudvsem", str(internal_source_response.data))
self.assertEqual(has_vacancies_response.status_code, status.HTTP_200_OK)
self.assertEqual(
has_vacancies_response.data["data"][0]["uid"],
str(organization.uid),
)
@override_settings(ORGANIZATIONS_V2_ALLOW_ANONYMOUS=True)
def test_dev_flag_allows_anonymous_access(self):
self.client.force_authenticate(user=None)
Organization.objects.create(
name='ООО "Без токена"',
inn="7766666666",
kpp="776601001",
ogrn="1027700132666",
)
response = self.client.get(
reverse("api_v2:organizations:organizations-list"),
{"has_registry": "false"},
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["meta"]["pagination"]["total_count"], 1)
@override_settings(ORGANIZATIONS_V2_ALLOW_ANONYMOUS=False)
def test_without_dev_flag_requires_authentication(self):
self.client.force_authenticate(user=None)
response = self.client.get(reverse("api_v2:organizations:organizations-list"))
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)