====== 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