diff --git a/src/apps/exchange/state_corp_services.py b/src/apps/exchange/state_corp_services.py index 5cfc1ec..a0d519b 100644 --- a/src/apps/exchange/state_corp_services.py +++ b/src/apps/exchange/state_corp_services.py @@ -96,6 +96,10 @@ class StateCorpExchangeService: } data = { "organizations": cls._serialize_organizations(organizations), + "registry_memberships": cls._serialize_registry_memberships( + organizations=organizations, + actual_date=snapshot_date, + ), "industrial_certificates": cls._serialize_industrial_certificates( allowed_inns ), @@ -123,6 +127,7 @@ class StateCorpExchangeService: "package_id": package_id, "source_system": source_system, "produced_at": produced_at.isoformat(), + "actual_date": snapshot_date.isoformat(), "schema_version": cls.SCHEMA_VERSION, "sections": [key for key, items in data.items() if items], }, @@ -323,6 +328,47 @@ class StateCorpExchangeService: for item in organizations ] + @classmethod + def _serialize_registry_memberships( + cls, + *, + organizations: list[Organization], + actual_date: date, + ) -> list[dict[str, str | None]]: + organization_ids = [organization.id for organization in organizations] + if not organization_ids: + return [] + + memberships = ( + RegistryMembershipPeriod.objects.select_related("registry", "organization") + .filter( + organization_id__in=organization_ids, + registry__name__in=cls.ROSATOM_ROSCOSMOS_REGISTRY_NAMES, + started_at__lte=actual_date, + ) + .filter(Q(ended_at__isnull=True) | Q(ended_at__gt=actual_date)) + .order_by( + "registry__name", + "organization__mn_inn", + "started_at", + "id", + ) + ) + + return [ + { + "organization_inn": str(membership.organization.mn_inn), + "registry_name": membership.registry.name, + "started_at": membership.started_at.isoformat(), + "ended_at": ( + membership.ended_at.isoformat() + if membership.ended_at and membership.ended_at <= actual_date + else None + ), + } + for membership in memberships + ] + @classmethod def _serialize_industrial_certificates( cls, diff --git a/tests/apps/exchange/test_state_corp_services.py b/tests/apps/exchange/test_state_corp_services.py index 1c39544..f233c55 100644 --- a/tests/apps/exchange/test_state_corp_services.py +++ b/tests/apps/exchange/test_state_corp_services.py @@ -260,6 +260,7 @@ class StateCorpExchangeServiceTest(TestCase): package = StateCorpExchangeService.build_package(actual_date="2026-03-15") self.assertEqual(package.payload_counts["organizations"], 1) + self.assertEqual(package.payload_counts["registry_memberships"], 1) self.assertEqual(package.payload_counts["industrial_certificates"], 1) self.assertEqual(package.payload_counts["manufacturers"], 1) self.assertEqual(package.payload_counts["industrial_products"], 1) @@ -277,6 +278,15 @@ class StateCorpExchangeServiceTest(TestCase): self.assertEqual(payload["format"], StateCorpExchangeService.PAYLOAD_FORMAT) self.assertEqual(payload["manifest"]["source_system"], "mostovik") self.assertEqual(payload["data"]["organizations"][0]["inn"], "7707083893") + self.assertEqual( + payload["data"]["registry_memberships"][0], + { + "organization_inn": "7707083893", + "registry_name": "Реестр госкорпорации Росатом", + "started_at": "2026-01-01", + "ended_at": None, + }, + ) self.assertEqual( payload["data"]["industrial_certificates"][0]["certificate_number"], "cert-001", @@ -395,6 +405,13 @@ class StateCorpExchangeServiceTest(TestCase): [item["inn"] for item in payload["data"]["organizations"]], [str(target.mn_inn)], ) + self.assertEqual( + [ + (item["organization_inn"], item["registry_name"]) + for item in payload["data"]["registry_memberships"] + ], + [(str(target.mn_inn), "Реестр госкорпорации Роскосмос")], + ) self.assertEqual( [ item["registry_number"]