feat: expand platform APIs, sources, and test coverage
Some checks failed
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m53s
CI/CD Pipeline / Telegram Notify Success (push) Has been cancelled
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 2m54s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped
Some checks failed
CI/CD Pipeline / Run Tests (pull_request) Successful in 1m53s
CI/CD Pipeline / Telegram Notify Success (push) Has been cancelled
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (push) Has been cancelled
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 2m54s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped
This commit is contained in:
219
tests/apps/parsers/test_source_cards_views.py
Normal file
219
tests/apps/parsers/test_source_cards_views.py
Normal file
@@ -0,0 +1,219 @@
|
||||
"""Tests for frontend source cards API."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from apps.core.models import BackgroundJob, JobStatus
|
||||
from apps.parsers.models import FinancialReport, FinancialReportLine, ParserLoadLog
|
||||
from django.test import override_settings
|
||||
from django.urls import reverse
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from tests.apps.parsers.factories import (
|
||||
IndustrialCertificateRecordFactory,
|
||||
IndustrialProductRecordFactory,
|
||||
InspectionRecordFactory,
|
||||
ManufacturerRecordFactory,
|
||||
ParserLoadLogFactory,
|
||||
)
|
||||
from tests.apps.user.factories import UserFactory
|
||||
from tests.utils.fixtures import fake
|
||||
|
||||
|
||||
def _digits(length: int) -> str:
|
||||
return "".join(str(fake.random_int(0, 9)) for _ in range(length))
|
||||
|
||||
|
||||
class SourceCardsApiTestCase(APITestCase):
|
||||
def setUp(self):
|
||||
self.user = UserFactory.create_user()
|
||||
self.admin = UserFactory.create_user(is_staff=True)
|
||||
self.client.force_authenticate(self.user)
|
||||
|
||||
def test_source_cards_list_returns_aggregated_data(self):
|
||||
report = FinancialReport.objects.create(
|
||||
external_id=_digits(5),
|
||||
ogrn=_digits(13),
|
||||
file_name=f"fin_{_digits(5)}_{_digits(13)}.xlsx",
|
||||
file_hash=fake.sha256(raw_output=False),
|
||||
load_batch=1,
|
||||
status=FinancialReport.Status.SUCCESS,
|
||||
source=FinancialReport.SourceType.API,
|
||||
)
|
||||
FinancialReportLine.objects.create(
|
||||
report=report,
|
||||
form_code="1",
|
||||
line_code="1100",
|
||||
line_name="Активы",
|
||||
year=2025,
|
||||
period_start=100,
|
||||
period_end=200,
|
||||
)
|
||||
FinancialReportLine.objects.create(
|
||||
report=report,
|
||||
form_code="2",
|
||||
line_code="2110",
|
||||
line_name="Выручка",
|
||||
year=2025,
|
||||
period_start=300,
|
||||
period_end=400,
|
||||
)
|
||||
ParserLoadLogFactory(
|
||||
source=ParserLoadLog.Source.FNS_REPORTS,
|
||||
status="success",
|
||||
records_count=2,
|
||||
)
|
||||
InspectionRecordFactory()
|
||||
BackgroundJob.objects.create(
|
||||
task_id="job-inspections-active",
|
||||
task_name="apps.parsers.tasks.sync_inspections",
|
||||
status=JobStatus.STARTED,
|
||||
progress=63,
|
||||
progress_message="sync",
|
||||
user_id=self.user.id,
|
||||
meta={"source": ParserLoadLog.Source.INSPECTIONS},
|
||||
)
|
||||
|
||||
response = self.client.get(reverse("api_v1:sources:source-cards-list"))
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response.data["success"])
|
||||
cards = {item["slug"]: item for item in response.data["data"]}
|
||||
|
||||
self.assertIn("financial-indicators", cards)
|
||||
self.assertIn("planned-inspections", cards)
|
||||
|
||||
fns_card = cards["financial-indicators"]
|
||||
self.assertEqual(fns_card["records_count"], 2)
|
||||
self.assertEqual(fns_card["organizations_count"], 1)
|
||||
self.assertEqual(fns_card["status"], "success")
|
||||
self.assertFalse(fns_card["refresh_requires_params"])
|
||||
|
||||
inspections_card = cards["planned-inspections"]
|
||||
self.assertEqual(inspections_card["status"], "in_progress")
|
||||
self.assertEqual(inspections_card["progress"], 63)
|
||||
|
||||
def test_source_card_detail_returns_combined_minprom_stats(self):
|
||||
shared_inn = _digits(10)
|
||||
IndustrialCertificateRecordFactory(inn=shared_inn)
|
||||
IndustrialProductRecordFactory(inn=shared_inn)
|
||||
ManufacturerRecordFactory(inn=shared_inn)
|
||||
ParserLoadLogFactory(
|
||||
source=ParserLoadLog.Source.INDUSTRIAL,
|
||||
status="success",
|
||||
records_count=1,
|
||||
)
|
||||
ParserLoadLogFactory(
|
||||
source=ParserLoadLog.Source.INDUSTRIAL_PRODUCTS,
|
||||
status="success",
|
||||
records_count=1,
|
||||
)
|
||||
ParserLoadLogFactory(
|
||||
source=ParserLoadLog.Source.MANUFACTURES,
|
||||
status="success",
|
||||
records_count=1,
|
||||
)
|
||||
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"api_v1:sources:source-cards-detail",
|
||||
kwargs={"slug": "manufacturers-and-products"},
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response.data["success"])
|
||||
card = response.data["data"]
|
||||
|
||||
self.assertEqual(card["records_count"], 3)
|
||||
self.assertEqual(card["organizations_count"], 1)
|
||||
self.assertEqual(card["status"], "success")
|
||||
self.assertEqual(len(card["source_items"]), 3)
|
||||
self.assertEqual(card["source_items"][0]["latest_load"]["status"], "success")
|
||||
|
||||
def test_source_task_statuses_returns_table_rows(self):
|
||||
ParserLoadLogFactory(
|
||||
source=ParserLoadLog.Source.INDUSTRIAL,
|
||||
status="success",
|
||||
records_count=12,
|
||||
)
|
||||
ParserLoadLogFactory(
|
||||
source=ParserLoadLog.Source.INSPECTIONS,
|
||||
status="failed",
|
||||
records_count=0,
|
||||
)
|
||||
|
||||
response = self.client.get(reverse("api_v1:sources:source-cards-statuses"))
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertTrue(response.data["success"])
|
||||
rows = response.data["data"]
|
||||
self.assertGreaterEqual(len(rows), 1)
|
||||
|
||||
row = rows[0]
|
||||
self.assertIn("row_number", row)
|
||||
self.assertIn("source", row)
|
||||
self.assertIn("actualized_at", row)
|
||||
self.assertIn("next_update_at", row)
|
||||
self.assertIn("records_count", row)
|
||||
self.assertIn("organizations_count", row)
|
||||
self.assertIn("status", row)
|
||||
self.assertIn("status_label", row)
|
||||
self.assertIn("active_tasks", row)
|
||||
|
||||
@override_settings(
|
||||
FNS_WATCH_DIRECTORY="/tmp/mostovik-test-fns/watch",
|
||||
FNS_PROCESSED_DIRECTORY="/tmp/mostovik-test-fns/processed",
|
||||
FNS_FAILED_DIRECTORY="/tmp/mostovik-test-fns/failed",
|
||||
)
|
||||
def test_refresh_creates_background_job_and_returns_task(self):
|
||||
self.client.force_authenticate(self.admin)
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"api_v1:sources:source-cards-refresh",
|
||||
kwargs={"slug": "financial-indicators"},
|
||||
),
|
||||
{},
|
||||
format="json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
|
||||
self.assertTrue(response.data["success"])
|
||||
payload = response.data["data"]
|
||||
self.assertEqual(payload["source_card"], "financial-indicators")
|
||||
self.assertEqual(len(payload["tasks"]), 1)
|
||||
|
||||
task_id = payload["tasks"][0]["task_id"]
|
||||
self.assertTrue(
|
||||
BackgroundJob.objects.filter(
|
||||
task_id=task_id,
|
||||
task_name="apps.parsers.tasks.scan_fns_directory",
|
||||
user_id=self.admin.id,
|
||||
).exists()
|
||||
)
|
||||
|
||||
def test_refresh_procurements_requires_region_code(self):
|
||||
self.client.force_authenticate(self.admin)
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"api_v1:sources:source-cards-refresh",
|
||||
kwargs={"slug": "public-procurements"},
|
||||
),
|
||||
{},
|
||||
format="json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertFalse(response.data["success"])
|
||||
|
||||
def test_refresh_forbidden_for_regular_user(self):
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"api_v1:sources:source-cards-refresh",
|
||||
kwargs={"slug": "financial-indicators"},
|
||||
),
|
||||
{},
|
||||
format="json",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
Reference in New Issue
Block a user