feat(organizations): migrate source storage to polymorphic records

This commit is contained in:
2026-05-19 10:23:53 +02:00
parent 19a7d5a91c
commit 4ca2fa25d5
44 changed files with 7129 additions and 1551 deletions

View File

@@ -20,6 +20,10 @@ from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from openpyxl import Workbook
from organizations.models import Organization
from organizations.source_ingestion import (
OrganizationSourceIngestionService,
SourceRecordInput,
)
from rest_framework import status
from rest_framework.test import APITestCase
@@ -67,6 +71,32 @@ def _build_fns_zip_bytes(file_map: dict[str, bytes]) -> bytes:
return buf.getvalue()
def _save_source_record(
*,
source: str,
external_id: str,
inn: str = "",
ogrn: str = "",
organization_name: str = "Test organization",
title: str = "Source record",
payload: dict | None = None,
) -> None:
OrganizationSourceIngestionService.save_records(
source=source,
load_batch=1,
records=[
SourceRecordInput(
external_id=external_id,
title=title,
organization_name=organization_name,
inn=inn,
ogrn=ogrn,
payload=payload or {},
)
],
)
def _create_procurement_record() -> ProcurementRecord:
return ProcurementRecord.objects.create(
load_batch=fake.random_int(min=1, max=1000),
@@ -442,35 +472,33 @@ class ParsersViewSetTest(APITestCase):
self.assertNotIn("kpp", detail)
def test_dashboard_data_exposes_source_groups_for_page(self):
GenericParserRecord.objects.create(
load_batch=1,
_save_source_record(
source=ParserLoadLog.Source.PROCUREMENTS_44FZ,
external_id="eis-44fz-1",
organization_name="Customer 1",
title="EIS 44-FZ notice 1",
payload={"registry": "44fz"},
)
GenericParserRecord.objects.create(
load_batch=1,
_save_source_record(
source=ParserLoadLog.Source.PROCUREMENTS_44FZ,
external_id="eis-44fz-2",
organization_name="Customer 2",
title="EIS 44-FZ notice 2",
payload={"registry": "44fz"},
)
GenericParserRecord.objects.create(
load_batch=1,
_save_source_record(
source=ParserLoadLog.Source.TRUDVSEM,
external_id="trudvsem-1",
organization_name="Employer",
title="Vacancy",
payload={"registry": "trudvsem"},
)
FinancialReport.objects.create(
_save_source_record(
source=ParserLoadLog.Source.FNS_REPORTS,
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,
organization_name="FNS organization",
title="FNS report",
)
self.client.force_authenticate(self.user)
@@ -513,17 +541,14 @@ class ParsersViewSetTest(APITestCase):
mn_ogrn=1107746880031,
)
RegistryMembershipPeriodFactory(organization=registry_organization)
FinancialReport.objects.create(
_save_source_record(
source=ParserLoadLog.Source.FNS_REPORTS,
external_id=_digits(5),
ogrn=str(registry_organization.mn_ogrn),
file_name=f"fin_{_digits(5)}_{registry_organization.mn_ogrn}.xlsx",
file_hash=fake.sha256(raw_output=False),
load_batch=1,
status=FinancialReport.Status.SUCCESS,
source=FinancialReport.SourceType.API,
organization_name="Registry FNS organization",
title="FNS report",
)
GenericParserRecord.objects.create(
load_batch=1,
_save_source_record(
source=ParserLoadLog.Source.UNFAIR_SUPPLIERS,
external_id="unfair-1",
title="Unfair supplier record",
@@ -561,36 +586,40 @@ class ParsersViewSetTest(APITestCase):
roscosmos_membership = RegistryMembershipPeriodFactory(
organization=roscosmos_organization
)
FinancialReport.objects.create(
_save_source_record(
source=ParserLoadLog.Source.FNS_REPORTS,
external_id=_digits(5),
ogrn=str(rosatom_organization.mn_ogrn),
file_name=f"fin_{_digits(5)}_{rosatom_organization.mn_ogrn}.xlsx",
file_hash=fake.sha256(raw_output=False),
load_batch=1,
status=FinancialReport.Status.SUCCESS,
source=FinancialReport.SourceType.API,
organization_name="Rosatom",
title="FNS report",
)
IndustrialCertificateRecordFactory(
_save_source_record(
source=ParserLoadLog.Source.INDUSTRIAL,
external_id="industrial-registry-analytics",
title="Industrial certificate",
organization_name="Rosatom",
inn=str(rosatom_organization.mn_inn),
ogrn=str(rosatom_organization.mn_ogrn),
)
GenericParserRecord.objects.create(
load_batch=1,
_save_source_record(
source=ParserLoadLog.Source.UNFAIR_SUPPLIERS,
external_id="unfair-registry-analytics",
title="Risk signal",
inn=str(roscosmos_organization.mn_inn),
ogrn=str(roscosmos_organization.mn_ogrn),
)
GenericParserRecord.objects.create(
load_batch=1,
_save_source_record(
source=ParserLoadLog.Source.FEDRESURS_BANKRUPTCY,
external_id="bankruptcy-registry-analytics",
title="Bankruptcy risk signal",
inn=str(roscosmos_organization.mn_inn),
ogrn=str(roscosmos_organization.mn_ogrn),
)
InspectionRecordFactory(
_save_source_record(
source=ParserLoadLog.Source.INSPECTIONS,
external_id="inspection-registry-analytics",
title="Inspection risk signal",
organization_name="Rosatom",
inn=str(rosatom_organization.mn_inn),
ogrn=str(rosatom_organization.mn_ogrn),
)