feat(admin): improve uploads and dashboard UX

This commit is contained in:
2026-03-23 16:07:11 +01:00
parent 45bca018b5
commit ef9763692d
22 changed files with 2531 additions and 212 deletions

View File

@@ -1,15 +1,31 @@
"""Tests for core admin configurations."""
from datetime import timedelta
from datetime import date, timedelta
from unittest.mock import patch
from apps.core.admin import BackgroundJobAdmin
from apps.core.models import BackgroundJob
from apps.parsers.models import FinancialReport, FinancialReportLine, ParserLoadLog
from django.contrib.admin.sites import AdminSite
from django.contrib.messages.storage.fallback import FallbackStorage
from django.test import RequestFactory, TestCase
from django.urls import reverse
from django.utils import timezone
from tests.apps.parsers.factories import (
IndustrialCertificateRecordFactory,
InspectionRecordFactory,
ManufacturerRecordFactory,
ParserLoadLogFactory,
ProcurementRecordFactory,
ProxyFactory,
)
from tests.apps.registers.factories import (
OrganizationFactory,
RegisterFactory,
RegisterUploadFactory,
RegistryMembershipPeriodFactory,
)
from tests.apps.user.factories import UserFactory
from tests.utils.fixtures import fake
@@ -94,3 +110,97 @@ class CoreAdminTest(TestCase):
revoke_mock.assert_called_once_with(job.task_id, terminate=True)
job.refresh_from_db()
self.assertEqual(job.status, "revoked")
class AdminDashboardTest(TestCase):
def setUp(self):
self.user = UserFactory.create_superuser()
self.client.force_login(self.user)
def test_admin_index_renders_custom_dashboard_with_live_metrics(self):
primary_registry = RegisterFactory(name="Реестр Росатом ОПК тестовый")
secondary_registry = RegisterFactory(name="Реестр Роскосмос ГОЗ тестовый")
primary_upload = RegisterUploadFactory(
registry=primary_registry,
actual_date=date(2026, 3, 20),
rows_count=24,
)
secondary_upload = RegisterUploadFactory(
registry=secondary_registry,
actual_date=date(2026, 3, 21),
rows_count=11,
)
first_org = OrganizationFactory(pn_name='АО "Росатом Тест"')
second_org = OrganizationFactory(pn_name='АО "Роскосмос Тест"')
RegistryMembershipPeriodFactory(
registry=primary_registry,
organization=first_org,
started_by_upload=primary_upload,
)
RegistryMembershipPeriodFactory(
registry=secondary_registry,
organization=second_org,
started_by_upload=secondary_upload,
)
report = FinancialReport.objects.create(
external_id="fns-dashboard-1",
ogrn="1027700000001",
file_name="fin_dashboard_1.xlsx",
file_hash="fns-dashboard-file-hash-1",
load_batch=101,
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=10,
period_end=15,
)
IndustrialCertificateRecordFactory(inn="7700000001")
ManufacturerRecordFactory(inn="7700000002")
InspectionRecordFactory(inn="7800000001")
ProcurementRecordFactory(region_code="77", customer_inn="7700000001")
ProcurementRecordFactory(region_code="77", customer_inn="7700000002")
ProcurementRecordFactory(region_code="78", customer_inn="7800000001")
ProxyFactory(is_active=True)
ParserLoadLogFactory(
source=ParserLoadLog.Source.PROCUREMENTS,
status="success",
records_count=3,
)
ParserLoadLogFactory(
source=ParserLoadLog.Source.INDUSTRIAL,
status="failed",
records_count=0,
error_message="Источник временно недоступен",
)
response = self.client.get(reverse("admin:index"))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Панель данных и загрузок")
self.assertContains(response, "Обзор")
self.assertContains(response, "Аналитика")
self.assertContains(response, "Админка")
self.assertContains(response, "Покрытие по внешним данным")
self.assertContains(response, "Топ регионов по закупкам")
self.assertContains(response, "Реестр Росатом ОПК тестовый")
self.assertContains(response, "Реестр Роскосмос ГОЗ тестовый")
self.assertContains(response, "Москва")
self.assertContains(response, "Санкт-Петербург")
self.assertContains(response, "Источник временно недоступен")
self.assertContains(
response,
reverse("admin:registers_registerupload_upload_excel"),
)
self.assertContains(
response,
reverse("admin:parsers_financialreport_upload_excel"),
)