fix(cuod-bundle): почистить FK orphans в seed (antenna, deliverable_type, ground_station)

Orphan FK references в seed данных bundle v1.2.1 — references на codes которых
нет в target словарях. Bundle import не валидирует x-references (privileged
data load), поэтому records ингестились с broken FK. На prod такие orphans
видны через ReferenceValidator при попытке update + через OrphanReferenceScanner.

Найдено через scan по 6 FK relations (antenna, consumer, deliverable_type,
orbital_regime, spacecraft×2):

1. antenna.ground_station (4 orphans):
   - GS_MOSCOW → MOSCOW_OTRADNOE (already существует)
   - GS_KHANTY/KRASNOYARSK/KHABAROVSK → добавили новые ground_station records
     (KHANTY_MANSIYSK_NPC, KRASNOYARSK_NPC, KHABAROVSK_NPC) — реальные станции
     НИЦ ПД ОМЗ Роскосмоса.

2. deliverable_type.typical_processing_level (3 orphans):
   - RADIANCE_L1B: L1 → L1B (businessKey hints L1B)
   - ORTHO_L1C: L1 → L1C (businessKey hints L1C)
   - SURFACE_REFL_L2A: L2 → L2A (businessKey hints L2A)

3. spacecraft.status — already исправлено в commit 5d5b03c (ACTIVE → OPERATIONAL).
   На prod 4 records остались с ACTIVE из старого import — нужен manual PATCH
   через writer API либо TRUNCATE + restart bundle import.

Verified: local seed scan теперь returns 0 orphans across all 6 FK relations.

Prod cleanup TODO (отдельный manual step, требует admin Keycloak token):
- spacecraft.status: 4 records (1999-068A, 2014-016A, 2015-028A, 2024-149E) → OPERATIONAL
- antenna.ground_station: 4 records → новые codes (MOSCOW_OTRADNOE / KHANTY_MANSIYSK_NPC / etc)
- deliverable_type.typical_processing_level: 3 records → L1B/L1C/L2A
This commit is contained in:
Zimin A.N.
2026-05-08 00:01:01 +03:00
parent cfe26a07a7
commit c12f515f43
3 changed files with 114 additions and 12 deletions
@@ -1,6 +1,6 @@
[
{ "businessKey": "GS_MOSCOW_A1", "data": { "code": "GS_MOSCOW_A1", "name": { "ru-RU": "Антенна А1 (НПЦ ОМЗ Москва)", "en-US": "Antenna A1 (Moscow GS)" }, "ground_station": "GS_MOSCOW", "diameter_m": 9.0, "supported_bands": ["X_BAND", "L_BAND"], "g_t_db_per_k": 32, "status": "active" } },
{ "businessKey": "GS_KHANTY_A1", "data": { "code": "GS_KHANTY_A1", "name": { "ru-RU": "Антенна А1 (Ханты-Мансийск)", "en-US": "Antenna A1 (Khanty-Mansiysk)" }, "ground_station": "GS_KHANTY", "diameter_m": 7.3, "supported_bands": ["X_BAND"], "g_t_db_per_k": 30, "status": "active" } },
{ "businessKey": "GS_KRASNOYARSK_A1", "data": { "code": "GS_KRASNOYARSK_A1", "name": { "ru-RU": "Антенна А1 (Красноярск)", "en-US": "Antenna A1 (Krasnoyarsk)" }, "ground_station": "GS_KRASNOYARSK", "diameter_m": 9.0, "supported_bands": ["X_BAND", "L_BAND"], "g_t_db_per_k": 32, "status": "active" } },
{ "businessKey": "GS_KHABAROVSK_A1", "data": { "code": "GS_KHABAROVSK_A1", "name": { "ru-RU": "Антенна А1 (Хабаровск)", "en-US": "Antenna A1 (Khabarovsk)" }, "ground_station": "GS_KHABAROVSK", "diameter_m": 9.0, "supported_bands": ["X_BAND"], "g_t_db_per_k": 31, "status": "active" } }
{ "businessKey": "GS_MOSCOW_A1", "data": { "code": "GS_MOSCOW_A1", "name": { "ru-RU": "Антенна А1 (НПЦ ОМЗ Москва)", "en-US": "Antenna A1 (Moscow GS)" }, "ground_station": "MOSCOW_OTRADNOE", "diameter_m": 9.0, "supported_bands": ["X_BAND", "L_BAND"], "g_t_db_per_k": 32, "status": "active" } },
{ "businessKey": "GS_KHANTY_A1", "data": { "code": "GS_KHANTY_A1", "name": { "ru-RU": "Антенна А1 (Ханты-Мансийск)", "en-US": "Antenna A1 (Khanty-Mansiysk)" }, "ground_station": "KHANTY_MANSIYSK_NPC", "diameter_m": 7.3, "supported_bands": ["X_BAND"], "g_t_db_per_k": 30, "status": "active" } },
{ "businessKey": "GS_KRASNOYARSK_A1", "data": { "code": "GS_KRASNOYARSK_A1", "name": { "ru-RU": "Антенна А1 (Красноярск)", "en-US": "Antenna A1 (Krasnoyarsk)" }, "ground_station": "KRASNOYARSK_NPC", "diameter_m": 9.0, "supported_bands": ["X_BAND", "L_BAND"], "g_t_db_per_k": 32, "status": "active" } },
{ "businessKey": "GS_KHABAROVSK_A1", "data": { "code": "GS_KHABAROVSK_A1", "name": { "ru-RU": "Антенна А1 (Хабаровск)", "en-US": "Antenna A1 (Khabarovsk)" }, "ground_station": "KHABAROVSK_NPC", "diameter_m": 9.0, "supported_bands": ["X_BAND"], "g_t_db_per_k": 31, "status": "active" } }
]
@@ -1,8 +1,8 @@
[
{"businessKey": "RAW_TELEMETRY", "data": {"code": "RAW_TELEMETRY", "name": {"ru-RU": "Сырая телеметрия", "en-US": "Raw telemetry"}, "category": "raw", "typical_processing_level": "L0", "status": "active"}},
{ "businessKey": "RADIANCE_L1B", "data": { "code": "RADIANCE_L1B", "name": { "ru-RU": "Калиброванная радиация (L1B)", "en-US": "Calibrated radiance (L1B)" }, "category": "calibrated", "typical_processing_level": "L1", "status": "active" } },
{ "businessKey": "ORTHO_L1C", "data": { "code": "ORTHO_L1C", "name": { "ru-RU": "Ортокорректированный продукт (L1C)", "en-US": "Orthorectified product (L1C)" }, "category": "geocorrected", "typical_processing_level": "L1", "status": "active" } },
{ "businessKey": "SURFACE_REFL_L2A", "data": { "code": "SURFACE_REFL_L2A", "name": { "ru-RU": "Отражательная способность поверхности (L2A)", "en-US": "Surface reflectance (L2A)" }, "category": "analysis_ready", "typical_processing_level": "L2", "status": "active" } },
{"businessKey": "RADIANCE_L1B", "data": {"code": "RADIANCE_L1B", "name": {"ru-RU": "Калиброванная радиация (L1B)", "en-US": "Calibrated radiance (L1B)"}, "category": "calibrated", "typical_processing_level": "L1B", "status": "active"}},
{"businessKey": "ORTHO_L1C", "data": {"code": "ORTHO_L1C", "name": {"ru-RU": "Ортокорректированный продукт (L1C)", "en-US": "Orthorectified product (L1C)"}, "category": "geocorrected", "typical_processing_level": "L1C", "status": "active"}},
{"businessKey": "SURFACE_REFL_L2A", "data": {"code": "SURFACE_REFL_L2A", "name": {"ru-RU": "Отражательная способность поверхности (L2A)", "en-US": "Surface reflectance (L2A)"}, "category": "analysis_ready", "typical_processing_level": "L2A", "status": "active"}},
{"businessKey": "INDEX_NDVI", "data": {"code": "INDEX_NDVI", "name": {"ru-RU": "NDVI / вегетационные индексы", "en-US": "NDVI / vegetation indices"}, "category": "thematic_map", "typical_processing_level": "L3", "status": "active"}},
{"businessKey": "DEM", "data": {"code": "DEM", "name": {"ru-RU": "Цифровая модель рельефа (DEM)", "en-US": "Digital Elevation Model (DEM)"}, "category": "thematic_map", "typical_processing_level": "L3", "status": "active"}},
{"businessKey": "LAND_COVER_MAP", "data": {"code": "LAND_COVER_MAP", "name": {"ru-RU": "Карта землепользования", "en-US": "Land cover map"}, "category": "thematic_map", "typical_processing_level": "L4", "status": "active"}},
@@ -101,5 +101,107 @@
},
"status": "OPERATIONAL"
}
},
{
"businessKey": "KHANTY_MANSIYSK_NPC",
"data": {
"code": "KHANTY_MANSIYSK_NPC",
"name": {
"ru-RU": "НИЦ ПД ОМЗ Ханты-Мансийск",
"en-US": "NIC PD OMZ Khanty-Mansiysk"
},
"location": {
"ru-RU": "Ханты-Мансийск, ХМАО — Югра, Россия",
"en-US": "Khanty-Mansiysk, Khanty-Mansi Autonomous Okrug, Russia"
},
"country": "RU",
"lat": 61.0042,
"lon": 69.0019,
"elevation_m": 50,
"elevation_min_deg": 5,
"antennas": [
{
"id": "A1",
"diameter_m": 7.3,
"bands": ["X_BAND"],
"rx_capable": true,
"tx_capable": false,
"g_t_db_per_k": 30
}
],
"operator": {
"ru-RU": "НИЦ ПД ОМЗ",
"en-US": "NIC PD OMZ"
},
"status": "OPERATIONAL"
}
},
{
"businessKey": "KRASNOYARSK_NPC",
"data": {
"code": "KRASNOYARSK_NPC",
"name": {
"ru-RU": "НИЦ ПД ОМЗ Красноярск",
"en-US": "NIC PD OMZ Krasnoyarsk"
},
"location": {
"ru-RU": "Красноярск, Красноярский край, Россия",
"en-US": "Krasnoyarsk, Krasnoyarsk Krai, Russia"
},
"country": "RU",
"lat": 56.0184,
"lon": 92.8672,
"elevation_m": 200,
"elevation_min_deg": 5,
"antennas": [
{
"id": "A1",
"diameter_m": 9.0,
"bands": ["X_BAND", "L_BAND"],
"rx_capable": true,
"tx_capable": false,
"g_t_db_per_k": 32
}
],
"operator": {
"ru-RU": "НИЦ ПД ОМЗ",
"en-US": "NIC PD OMZ"
},
"status": "OPERATIONAL"
}
},
{
"businessKey": "KHABAROVSK_NPC",
"data": {
"code": "KHABAROVSK_NPC",
"name": {
"ru-RU": "НИЦ ПД ОМЗ Хабаровск",
"en-US": "NIC PD OMZ Khabarovsk"
},
"location": {
"ru-RU": "Хабаровск, Хабаровский край, Россия",
"en-US": "Khabarovsk, Khabarovsk Krai, Russia"
},
"country": "RU",
"lat": 48.4647,
"lon": 135.0719,
"elevation_m": 80,
"elevation_min_deg": 5,
"antennas": [
{
"id": "A1",
"diameter_m": 9.0,
"bands": ["X_BAND"],
"rx_capable": true,
"tx_capable": false,
"g_t_db_per_k": 31
}
],
"operator": {
"ru-RU": "НИЦ ПД ОМЗ",
"en-US": "NIC PD OMZ"
},
"status": "OPERATIONAL"
}
}
]