====== 2.5 Migrationsplan — Legacy → Neue Architektur ====== //Stand: 2026-03-05// Übergeordnet: [[de:int:wvdsshell:notes:02-cafm:start|Asset-Architektur — Gesamtübersicht]] Verwandt: [[de:int:wvdsshell:notes:02-cafm:legacy-analysis|2.4 Legacy-Analyse]] | [[de:int:wvdsshell:notes:02-cafm:asset-model|2.2 Asset-Modell]] ===== Migrationsphasen (Gesamt) ===== ^ Phase ^ System ^ Ziel ^ Status ^ | 1 | ENIVERSCAFM auth.* + ENIVERSSIAM core.person | ENIVERSSIAM | ✓ Abgeschlossen | | 2 | LD/ENIVERS (tblPerson/tblRolle, BESTAND) | ENIVERSSIAM + ENIVERSCAFM | ✓ Abgeschlossen | | 3 | AMED (APPMASTER, MOTORMASTER, EZAMASTER, AVI_Equip, tblLocationKV) | ENIVERSCAFM | Ausstehend | | 4 | TecDB (Rohrdatenbank) + WIS/PROOF | ENIVERSCAFM + ENIVERSPIMS | Ausstehend | | 5 | ENIVERSASYS aufbauen; Feature-Flags aus ENIVERSCAFM auslagern | ENIVERSSYS | Ausstehend | Details Phase 1–2: [[de:int:wvdsshell:notes:01-siam:auth-migration|Auth-Migration — Legacy-Systeme]] ===== Phase 3: AMED → ENIVERSCAFM ===== ==== Mapping-Tabelle ==== ^ AMED-Quelle ^ Spalte(n) ^ Ziel ^ Ziel-Spalte(n) ^ | APPMASTER | erwAppNr | asset.item | legacy_id, legacy_source='AMED' | | APPMASTER | AppTyp, AppGruppe | asset.item | type_code='device' | | APPMASTER | AppNr, AppBenennung | asset.item | item_number, name | | APPMASTER | Werk, Bereich, Abteilung | asset.item | branch_id, location_id (via org.*) | | APPMASTER | Alle weiteren Felder | asset.item.properties | JSON-Objekt | | MOTORMASTER | MoNr, MoBenennung | asset.item | type_code='motor', item_number, name | | MOTORMASTER | FK → APPMASTER | asset.item_installation | fl_item_id → device, eq_item_id → motor| | MOTORMASTER | Alle weiteren Felder | asset.item.properties | JSON-Objekt | | EZAMASTER | EZA-Typ, SIL-Level | asset.item.properties | JSON in type_code='instrument' | | EZAMASTER | FK → APPMASTER | asset.item | parent_id → device | | AVI_Equip | RegNr, INT_NR | asset.item | type_code='safety', item_number | | AVI_Equip | FK → APPMASTER | asset.item | parent_id → device | | tblLocationKV | KV-Nummer, KV-Code | asset.electrical_connection | kv_number, kv_code | | tblLocationKV | FK → Motor/Gerät | asset.electrical_connection | device_id, motor_id | ==== Migrationsskript-Reihenfolge ==== 1. org.branch, org.site, org.location befüllen (aus AMED Werk/Bereich/Abteilung) 2. asset.item für APPMASTER (type_code='device') 3. asset.item für MOTORMASTER (type_code='motor') 4. asset.item_installation (MOTORMASTER.FK → APPMASTER Verknüpfung) 5. asset.item für EZAMASTER (type_code='instrument', parent_id=device) 6. asset.item für AVI_Equip (type_code='safety', parent_id=device) 7. asset.electrical_connection aus tblLocationKV ==== Validierung ==== -- Erwartete Counts nach Migration -- device: SELECT COUNT(*) FROM APPMASTER → Soll = asset.item WHERE type_code='device' -- motor: SELECT COUNT(*) FROM MOTORMASTER → Soll = asset.item WHERE type_code='motor' -- Aktuell erfüllt: device=11.652, motor=8.461 ✓ (bereits migriert) ===== Phase 4a: TecDB → ENIVERSCAFM ===== ==== Mapping ==== ^ TecDB-Quelle ^ Ziel ^ Bemerkung ^ | tblRohrMaster | asset.item | type_code='piping', properties=JSON | | tblObjektEigenschaft | asset.item.properties | JSON-Merge; EAV → JSON | | tblObjekt (Hierarchie)| asset.item.parent_id | Rohrsegment-Hierarchie | ==== EAV → JSON Konvertierung ==== -- EAV zu JSON: pro tblRohrMaster-Zeile alle zugehörigen Eigenschaften als JSON INSERT INTO asset.item (legacy_id, legacy_source, type_code, name, properties) SELECT CAST(r.idRohr AS VARCHAR), 'TECDB', 'piping', r.strObjName, ( SELECT e.strEigenschaftsName, oe.varWert FROM tblObjektEigenschaft oe JOIN tblEigenschaft e ON e.idEigenschaft = oe.fiEigenschaft WHERE oe.fiObjekt = r.idRohr FOR JSON PATH ) FROM tblRohrMaster r Nach der Migration: Trigger ''trgRohrMasterInsertUpdate'' und ''trgObjektEigenschaftUpdate'' entfallen. View-Generierung übernimmt ''trg_regen_type_views''. ===== Phase 4b: WIS/PROOF → ENIVERSPIMS ===== ==== Mapping ==== ^ WIS-Quelle ^ Ziel ^ Bemerkung ^ | Common (RuleBase) | inspection.rule | Alle rule_type-Codes | | TimeTrain | inspection.task | Offene Tasks; Status übersetzen | | TimeTrain_Hist (HIST) | hist.task_archive | Append-Only übernehmen | | PROOF-DB | proof.measurement, proof.certificate | Selektiv (nach Analyse) | | tf_GetCommonExtended | inspection.v_task_detail (View) | Als View in ENIVERSPIMS | ==== Synonym-Ablösung ==== WIS hat 63 Synonyme auf AMED, HIST, AUDIT. In ENIVERSPIMS: * **Synonyme entfallen** — alle Daten liegen lokal in ENIVERSPIMS * ''Common.IdSub'' → ''inspection.rule.item_id'' (FK auf ENIVERSCAFM.asset.item) * HIST.dbo.TimeTrain_Hist → ''hist.task_archive'' (lokal, Append-Only) * AUDIT.dbo.Common → ''audit.*'' in ENIVERSCAFM (bereits vorhanden) ===== Phase 5: ENIVERSASYS (Feature-Flags) ===== Feature-Flags liegen aktuell in ENIVERSCAFM (ENIVERSASYS-DB-Konzept). Phase 5 lagert sie in eine dedizierte ENIVERSSYS-Datenbank aus: ENIVERSCAFM.ENIVERSASYS → ENIVERSSYS (neue DB) Tabellen: feature_flag, feature_rollout, feature_assignment Zugriff: nur via Gateway.Service /api/v1/features Endpoint ===== Greenfield-Workflow (neue Anlage ohne Legacy-Daten) ===== Für Standorte/Anlagen, die **noch keine historischen Daten** haben: Schritt 1 — Organisationsstruktur anlegen INSERT org.branch (name='Werk Süd', ...) INSERT org.site (branch_id=..., name='Halle A', ...) INSERT org.location (site_id=..., name='Zone 1', ...) Schritt 2 — Technische Plätze anlegen (Status: 'planned') INSERT asset.item ( type_code='device', status_code='planned', item_number='T-A1-001', -- Technischer Platz Kennzeichen name='Pumpe P-001', branch_id=..., location_id=..., properties='{}' ) -- UI-Formular wird automatisch aus asset.property_schema generiert Schritt 3 — Prüfregeln definieren (ENIVERSPIMS) INSERT inspection.rule ( item_id=..., -- FK → asset.item rule_type='GP', -- Gesetzliche Prüfung interval_value=12, interval_unit='MM', -- monatlich valid_from='2026-01-01' ) Schritt 4 — Equipment einbauen (Status: 'active') -- Equipment-Datensatz anlegen INSERT asset.item ( type_code='motor', status_code='active', item_number='M-12345', -- Seriennummer o.ä. name='Motor ABB 7,5kW', properties='{"power_kw":7.5,"voltage_v":400,...}' ) -- Am TP einbauen INSERT asset.item_installation ( fl_item_id=..., -- TP (device) eq_item_id=..., -- Equipment (motor) installed_from='2026-03-01' ) -- TP auf 'active' setzen UPDATE asset.item SET status_code='active' WHERE id=... Schritt 5 — Elektrische Verbindung herstellen INSERT asset.electrical_connection ( device_id=..., motor_id=..., kv_number='KV-12', kv_code='P-A1-001-M' ) ===== Migrationsstrategie: Legacy-ID als Anker ===== Alle migrierten Datensätze behalten ihre Legacy-ID: -- Lookup: AMED-Objekt in neuer Datenbank finden SELECT * FROM asset.item WHERE legacy_source = 'AMED' AND legacy_id = '12345' -- APPMASTER.erwAppNr -- Lookup: TecDB-Rohr in neuer Datenbank finden SELECT * FROM asset.item WHERE legacy_source = 'TECDB' AND legacy_id = '678' -- tblRohrMaster.idRohr ''legacy_id'' und ''legacy_source'' bleiben dauerhaft erhalten (kein Löschen nach Migration). Sie dienen als Referenz für: * Parallelbetrieb während der Übergangsphase * Diagnose bei Datenproblemen * Historische Rückverfolgung