This commit is contained in:
marcus hinz
2026-06-20 14:40:33 +02:00
commit 93bb19abf0
32 changed files with 2827 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
*.bkp
.$*
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""Gemeinsames adesso-Styling für die Workshop-Folien.
Teal->Blau-Verlauf, Fira Sans, weiße Shapes + Coral-Akzente,
Header (Pill + Titel) und schlanke Fußzeile (Seitenzahl + adesso)."""
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.oxml.ns import qn
# ---- adesso Palette --------------------------------------------------------
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
INK = RGBColor(0x0E, 0x2A, 0x47) # tiefes Navy Text auf hellen Boxen / dunkle Füllungen
BLUE = RGBColor(0x00, 0x6E, 0xC7)
TEAL = RGBColor(0x28, 0xDC, 0xAA)
GREEN = RGBColor(0x76, 0xC8, 0x00)
CORAL = RGBColor(0xFF, 0x98, 0x68)
PINK = RGBColor(0xF5, 0x66, 0xBA)
TAUPE = RGBColor(0x88, 0x7D, 0x75)
LIGHT = RGBColor(0xD7, 0xE6, 0xF4) # helle, gedämpfte Schrift/Linien auf dem Verlauf
MUTE = RGBColor(0x6B, 0x77, 0x85) # mittleres Grau Text auf weißen Flächen
RECF = RGBColor(0xE6, 0xEF, 0xF8) # helle Kästchen in weißen Boxen
F = "Fira Sans"
FC = "Fira Sans Condensed"
def alpha(shape, opacity_pct):
"""Deckkraft (0-100) auf die Solid-Füllung setzen."""
srgb = shape._element.spPr.find(qn('a:solidFill')).find(qn('a:srgbClr'))
srgb.append(srgb.makeelement(qn('a:alpha'), {'val': str(int(opacity_pct * 1000))}))
def line_alpha(shape, opacity_pct):
ln = shape._element.spPr.find(qn('a:ln'))
srgb = ln.find(qn('a:solidFill')).find(qn('a:srgbClr'))
srgb.append(srgb.makeelement(qn('a:alpha'), {'val': str(int(opacity_pct * 1000))}))
def paint_background(s, width, height):
"""Teal->Blau-Verlauf als Folienhintergrund."""
bgr = s.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, width, height)
bgr.line.fill.background(); bgr.shadow.inherit = False
bgr.fill.gradient()
try:
bgr.fill.gradient_angle = 90.0
except Exception:
pass
st = bgr.fill.gradient_stops
st[0].position = 0.0; st[0].color.rgb = TEAL
st[1].position = 1.0; st[1].color.rgb = BLUE
return bgr
def chrome(s, title, page):
"""Header (Pill + Titel) + schlanke Fußzeile (Seitenzahl + adesso)."""
pill = s.shapes.add_shape(MSO_SHAPE.ROUNDED_RECTANGLE,
Inches(0.55), Inches(0.46), Inches(0.5), Inches(0.26))
pill.fill.background(); pill.line.color.rgb = WHITE; pill.line.width = Pt(1.5)
pill.shadow.inherit = False
try: pill.adjustments[0] = 0.5
except Exception: pass
def _t(x, y, w, h, t, size, color, bold=False, align=PP_ALIGN.LEFT, font=FC):
tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame
tf.word_wrap = True; tf.margin_left = tf.margin_right = Pt(0)
tf.margin_top = tf.margin_bottom = Pt(0)
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.name = font; r.font.color.rgb = color
_t(Inches(1.25), Inches(0.34), Inches(11), Inches(0.7), title, 30, WHITE, bold=True)
_t(Inches(0.55), Inches(7.06), Inches(1.0), Inches(0.3), str(page), 11, LIGHT)
_t(Inches(10.95), Inches(6.99), Inches(1.85), Inches(0.4), "adesso", 17, WHITE,
bold=True, align=PP_ALIGN.RIGHT)
BIN
View File
Binary file not shown.
+246
View File
@@ -0,0 +1,246 @@
#!/usr/bin/env python3
"""Workshop-Folien 'Vault Technischer Impuls': ruhig, visuell, wenig Text."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
# ---- Palette ---------------------------------------------------------------
INK = RGBColor(0x2A, 0x2F, 0x3A)
NAVY = RGBColor(0x1F, 0x3A, 0x5F)
ACCENT = RGBColor(0xC0, 0x49, 0x2F)
MUTE = RGBColor(0x8A, 0x93, 0xA0)
SOFT = RGBColor(0xE9, 0xEC, 0xEF) # heller Kasten
SOFT2 = RGBColor(0xDD, 0xE5, 0xEC) # heller Kasten blau
LINEC = RGBColor(0xC3, 0xC9, 0xD1)
BG = RGBColor(0xFF, 0xFF, 0xFF)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
F = "Calibri"
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
BLANK = prs.slide_layouts[6]
MX = Inches(0.95)
def slide(bg=BG):
s = prs.slides.add_slide(BLANK)
r = s.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, SW, SH)
r.fill.solid(); r.fill.fore_color.rgb = bg; r.line.fill.background()
r.shadow.inherit = False
s.shapes._spTree.remove(r._element); s.shapes._spTree.insert(2, r._element)
return s
def shape(s, kind, x, y, w, h, fill=None, line=None, lw=Pt(1)):
sh = s.shapes.add_shape(kind, x, y, w, h)
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
sh.shadow.inherit = False
return sh
def box(s, x, y, w, h, text="", fill=SOFT, tc=INK, size=15, bold=False,
rounded=True, line=None, sub=None, sub_c=None):
kind = MSO_SHAPE.ROUNDED_RECTANGLE if rounded else MSO_SHAPE.RECTANGLE
sh = shape(s, kind, x, y, w, h, fill=fill, line=line)
tf = sh.text_frame; tf.word_wrap = True
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_top = tf.margin_bottom = Pt(2)
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER
r = p.add_run(); r.text = text
r.font.size = Pt(size); r.font.bold = bold; r.font.name = F; r.font.color.rgb = tc
if sub:
p2 = tf.add_paragraph(); p2.alignment = PP_ALIGN.CENTER; p2.space_before = Pt(2)
r2 = p2.add_run(); r2.text = sub
r2.font.size = Pt(11); r2.font.name = F; r2.font.color.rgb = sub_c or MUTE
return sh
def text(s, x, y, w, h, runs, align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.TOP,
leading=1.1, space=0):
tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = anchor
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
p = tf.paragraphs[0]; p.alignment = align; p.line_spacing = leading; p.space_after = Pt(space)
for t, kw in runs:
r = p.add_run(); r.text = t
r.font.size = Pt(kw.get("size", 16)); r.font.bold = kw.get("bold", False)
r.font.italic = kw.get("italic", False); r.font.name = F
r.font.color.rgb = kw.get("color", INK)
return tb
def kicker(s, t):
tb = text(s, MX, Inches(0.62), Inches(11), Inches(0.4),
[(t.upper(), {"size": 12.5, "color": ACCENT, "bold": True})])
tb.text_frame.paragraphs[0].runs[0].font._rPr.set('spc', '240')
def head(s, t):
text(s, MX, Inches(1.0), Inches(11.4), Inches(0.9),
[(t, {"size": 32, "color": NAVY, "bold": True})])
shape(s, MSO_SHAPE.RECTANGLE, MX, Inches(1.78), Inches(0.6), Pt(4), fill=ACCENT)
def caption(s, t):
text(s, MX, Inches(6.62), Inches(11.4), Inches(0.6),
[(t, {"size": 16, "color": MUTE})], leading=1.15)
def vline(s, x, y, h, color=LINEC):
shape(s, MSO_SHAPE.RECTANGLE, x, y, Pt(1.6), h, fill=color)
# ===========================================================================
# TITEL
# ===========================================================================
s = slide(NAVY)
shape(s, MSO_SHAPE.RECTANGLE, 0, 0, Inches(0.24), SH, fill=ACCENT)
shape(s, MSO_SHAPE.RECTANGLE, MX, Inches(2.7), Inches(0.85), Pt(5), fill=ACCENT)
text(s, MX, Inches(1.7), Inches(10), Inches(0.5),
[("TECHNISCHER IMPULS", {"size": 14, "color": RGBColor(0xC6,0xD1,0xDE), "bold": True})]
).text_frame.paragraphs[0].runs[0].font._rPr.set('spc', '280')
text(s, MX, Inches(3.05), Inches(11.4), Inches(2.0),
[("LIS wohin", {"size": 50, "color": WHITE, "bold": True})])
text(s, MX, Inches(4.05), Inches(11.4), Inches(2.0),
[("technisch denken?", {"size": 50, "color": WHITE, "bold": True})])
# ===========================================================================
# FOLIE 1 Produkt oder Projekt (Balken-Bild)
# ===========================================================================
s = slide()
kicker(s, "Diagnose")
head(s, "Produkt oder Projekt?")
base = Inches(5.45) # Grundlinie
bw, gap = Inches(0.52), Inches(0.16)
def bars(cx_start, heights, colors, label):
n = len(heights)
for i, (hh, col) in enumerate(zip(heights, colors)):
x = cx_start + i * (bw + gap)
h = Inches(hh)
shape(s, MSO_SHAPE.ROUNDED_RECTANGLE, x, base - h, bw, h, fill=col)
total = n * bw + (n - 1) * gap
# Grundlinie
shape(s, MSO_SHAPE.RECTANGLE, cx_start, base, total, Pt(2), fill=LINEC)
text(s, cx_start, base + Inches(0.18), total, Inches(0.4),
[(label, {"size": 18, "color": NAVY, "bold": True})], align=PP_ALIGN.CENTER)
bars(Inches(1.5), [0.45, 0.5, 2.7, 0.5, 0.45],
[MUTE, MUTE, ACCENT, MUTE, MUTE], "Projekt")
bars(Inches(8.0), [1.7, 2.0, 1.8, 2.1, 1.7],
[NAVY, NAVY, NAVY, NAVY, NAVY], "Produkt")
# kleine neutrale Unterschriften
text(s, Inches(1.5), base + Inches(0.6), Inches(3.42), Inches(0.4),
[("tief in einer Dimension", {"size": 13, "color": MUTE})], align=PP_ALIGN.CENTER)
text(s, Inches(8.0), base + Inches(0.6), Inches(3.42), Inches(0.4),
[("breit über viele", {"size": 13, "color": MUTE})], align=PP_ALIGN.CENTER)
# ===========================================================================
# FOLIE 2 Eine Schicht dazwischen (Layer-Diagramm)
# ===========================================================================
s = slide()
kicker(s, "Architektur")
head(s, "Eine Schicht dazwischen")
cxL, cxR = MX, Inches(12.38)
full_w = cxR - cxL
# oben: Gruppe / Prozesse
top_y = Inches(2.2)
chips = ["Reporting", "DFÜ / Anlieferung", "Fusion"]
cw = Inches(3.2); cg = (full_w - 3 * cw) / 2
for i, c in enumerate(chips):
box(s, cxL + i * (cw + cg), top_y, cw, Inches(0.72), c,
fill=BG, tc=NAVY, size=15, bold=True, line=LINEC)
# Mitte: die Schicht (Hero)
mid_y = Inches(3.55)
box(s, cxL, mid_y, full_w, Inches(0.95),
"Integrations- & Abstraktionsschicht",
fill=NAVY, tc=WHITE, size=20, bold=True)
# unten: Systeme
bot_y = Inches(5.15)
labs = [("Labor A", "LIS"), ("Labor B", "LIS"), ("Vault", "LIS"), ("Labor C", "eigenes LIS")]
lw = Inches(2.65); lg = (full_w - 4 * lw) / 3
for i, (nm, sub) in enumerate(labs):
x = cxL + i * (lw + lg)
box(s, x, bot_y, lw, Inches(0.95), nm, fill=SOFT, tc=INK, size=16, bold=True,
sub=sub, sub_c=MUTE)
# Verbinder Schicht -> System
vline(s, x + lw / 2, mid_y + Inches(0.95), bot_y - (mid_y + Inches(0.95)))
# Verbinder oben -> Schicht
for i in range(3):
cx = cxL + i * (cw + cg) + cw / 2
vline(s, cx, top_y + Inches(0.72), mid_y - (top_y + Inches(0.72)))
caption(s, "Labore docken an und behalten ihr LIS. Die Schicht verbindet.")
# ===========================================================================
# FOLIE 3 Zustand oder Ereignis (Event Sourcing, visuell)
# ===========================================================================
s = slide()
kicker(s, "Modell")
head(s, "Zustand oder Ereignis")
cxL, cxR = MX, Inches(12.38)
full_w = cxR - cxL
# --- obere Spur: Zustand ---
ay = Inches(2.35)
text(s, cxL, ay - Inches(0.05), Inches(3), Inches(0.4),
[("Zustand", {"size": 15, "color": MUTE, "bold": True})])
zy = ay + Inches(0.42)
box(s, cxL, zy, Inches(2.4), Inches(0.95), "Probe", fill=SOFT, tc=INK, size=16, bold=True)
# Pfeil "überschreiben"
shape(s, MSO_SHAPE.RIGHT_ARROW, cxL + Inches(2.65), zy + Inches(0.27),
Inches(1.5), Inches(0.42), fill=LINEC)
text(s, cxL + Inches(2.55), zy - Inches(0.18), Inches(1.7), Inches(0.3),
[("überschreiben", {"size": 11, "color": MUTE, "italic": True})], align=PP_ALIGN.CENTER)
box(s, cxL + Inches(4.4), zy, Inches(2.7), Inches(0.95), "1 Abrechnung",
fill=BG, tc=NAVY, size=16, bold=True, line=LINEC)
# Trennlinie
shape(s, MSO_SHAPE.RECTANGLE, cxL, Inches(4.25), full_w, Pt(1.2), fill=LINEC)
# --- untere Spur: Ereignisse ---
by = Inches(4.55)
text(s, cxL, by - Inches(0.05), Inches(3), Inches(0.4),
[("Ereignisse", {"size": 15, "color": MUTE, "bold": True})])
ey = by + Inches(0.42)
ev = ["Eingang", "Messung", "Abrechnung", "Abrechnung"]
ew = Inches(1.85); eg = Inches(0.32)
for i, e in enumerate(ev):
x = cxL + i * (ew + eg)
col = ACCENT if e == "Abrechnung" else NAVY
box(s, x, ey, ew, Inches(0.85), e, fill=col, tc=WHITE, size=14, bold=True)
if i < len(ev) - 1:
shape(s, MSO_SHAPE.CHEVRON, x + ew + Inches(0.02), ey + Inches(0.24),
Inches(0.28), Inches(0.38), fill=LINEC)
# Pfeil zum abgeleiteten Zustand
last_x = cxL + 4 * (ew + eg)
shape(s, MSO_SHAPE.RIGHT_ARROW, last_x - Inches(0.05), ey + Inches(0.22),
Inches(0.7), Inches(0.42), fill=LINEC)
box(s, last_x + Inches(0.75), ey - Inches(0.05), Inches(2.7), Inches(0.95),
"Zustand", fill=SOFT2, tc=NAVY, size=15, bold=True,
sub="abgeleitet", sub_c=MUTE)
caption(s, "Der Zustand entsteht aus den Ereignissen Mehrfaches inklusive.")
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Vault_Impuls_Workshop.pptx")
prs.save(out)
print("saved", out)
+90
View File
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
"""Folie 10 Was bringt der Integrationsserver? Wichtige Funktionen (adesso-Stil, deutsch)."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, MUTE, RECF,
F, FC, chrome)
BG = RGBColor(0x0A, 0x3D, 0x6B)
SUBC = RGBColor(0x3C, 0x4A, 0x5A)
prs = Presentation(); prs.slide_width = Inches(13.333); prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
s = prs.slides.add_slide(prs.slide_layouts[6])
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), adj=None):
sh = s.shapes.add_shape(kind, Inches(x), Inches(y), Inches(w), Inches(h))
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if adj is not None:
try: sh.adjustments[0] = adj
except Exception: pass
sh.shadow.inherit = False
return sh
def txt(x, y, w, h, t, size=12, color=WHITE, bold=False, italic=False,
align=PP_ALIGN.LEFT, font=F, anchor=MSO_ANCHOR.MIDDLE):
tb = s.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h)); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = anchor
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.name = font; r.font.color.rgb = color
return tb
def card(x, y, w, h, title, body):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=WHITE, adj=0.06)
shp(MSO_SHAPE.RECTANGLE, x, y + 0.16, 0.12, h - 0.32, fill=CORAL)
txt(x + 0.32, y + 0.18, w - 0.48, 0.78, title, size=13.5, color=INK, bold=True,
anchor=MSO_ANCHOR.TOP)
txt(x + 0.32, y + 0.92, w - 0.52, h - 1.06, body, size=11, color=SUBC,
anchor=MSO_ANCHOR.TOP)
# ---- Hintergrund + Header --------------------------------------------------
shp(MSO_SHAPE.RECTANGLE, 0, 0, SW.inches, SH.inches, fill=BG)
chrome(s, "Was bringt der Integrationsserver?", 11)
shp(MSO_SHAPE.RECTANGLE, 0.45, 1.12, 0.16, 0.22, fill=CORAL)
txt(0.71, 1.05, 9.0, 0.34, "Wichtige Funktionen", size=15, color=WHITE, bold=True,
anchor=MSO_ANCHOR.MIDDLE)
cards = [
("Zentrale Anbindung (Adapter)",
"Jedes System über einen Adapter — neues System = neuer Adapter, ohne Eingriff in den Bestand."),
("Routing der Aufträge",
"Integriert mehrere LIS- und Abrechnungs-Instanzen — Aufträge werden gezielt an das passende LIS bzw. die richtige Abrechnung verteilt."),
("Routing Engine",
"Verteilt Events regelbasiert an die richtigen Ziele — z. B. Proben-Routing."),
("Event Store (append-only)",
"Kanonische Wahrheit, vollständige Historie, jederzeit Replay-fähig."),
("Projektionen / Read-Models",
"Bedarfsgerechte Sichten: Auftragsstatus, Reporting, Leistungsverzeichnis …"),
("Stammdaten / MDM",
"Single Point of Truth — Daten einmal pflegen, doppelte Stammdatenpflege entfällt."),
("Monitoring & Überwachung",
"Status, Fehler-Queues und Alerting für alle Schnittstellen an einer Stelle."),
("Audit-Trail, Replay & Archiv",
"Revisionssicher & manipulationssicher; Wiederaufsetzen per Replay; Langzeit-Archiv."),
]
cw, ch = 2.92, 2.45
cols = [0.45, 3.62, 6.79, 9.96]
rows = [1.58, 4.22]
for i, (title, body) in enumerate(cards):
card(cols[i % 4], rows[i // 4], cw, ch, title, body)
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie10.pptx")
prs.save(out)
print("saved", out)
+174
View File
@@ -0,0 +1,174 @@
#!/usr/bin/env python3
"""Folie 2 Grenzen der Vault-Integration (adesso-Styling).
Kette: Auftrag -> Auftragsannahme -> Schattenbuchhaltung (SPOT) -> Vault ->
Zusammenführung."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from adesso_style import (WHITE, INK, CORAL, LIGHT, RECF, F, FC,
alpha, line_alpha, paint_background, chrome)
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
s = prs.slides.add_slide(prs.slide_layouts[6])
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), rot=0):
sh = s.shapes.add_shape(kind, x, y, w, h)
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if rot: sh.rotation = rot
sh.shadow.inherit = False
return sh
def boxtext(sh, t, size=14, color=INK, bold=False, font=F):
tf = sh.text_frame; tf.word_wrap = True
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_left = tf.margin_right = Pt(4); tf.margin_top = tf.margin_bottom = Pt(1)
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.name = font; r.font.color.rgb = color
def txt(x, y, w, h, t, size=14, color=INK, bold=False, italic=False,
align=PP_ALIGN.LEFT, spc=None, lead=1.1, anchor=MSO_ANCHOR.TOP, font=F):
tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = anchor
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
p = tf.paragraphs[0]; p.alignment = align; p.line_spacing = lead
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.name = font; r.font.color.rgb = color
if spc: r.font._rPr.set('spc', str(spc))
return tb
paint_background(s, prs.slide_width, prs.slide_height)
chrome(s, "Grenzen der Vault-Integration?", 2)
# ---- Linke Spalte ----------------------------------------------------------
def claim(y, t, bold=False, sub=None):
shp(MSO_SHAPE.RECTANGLE, Inches(0.95), y + Inches(0.08), Inches(0.14), Inches(0.14), fill=CORAL)
txt(Inches(1.28), y, Inches(4.5), Inches(0.4), t, size=16.5, color=WHITE, bold=bold)
if sub:
txt(Inches(1.28), y + Inches(0.34), Inches(4.5), Inches(0.32), sub,
size=12.5, color=LIGHT, italic=True)
claim(Inches(2.2), "Middleware kapselt den Rand den Kern nicht", bold=True)
claim(Inches(2.95), "Mischaufträge nur als Schattenmodell",
sub="aufwändig · fragil · fehleranfällig")
claim(Inches(3.95), "die Fachwahrheit verlässt den Kern")
shp(MSO_SHAPE.RECTANGLE, Inches(0.95), Inches(4.95), Inches(0.5), Pt(3.5), fill=CORAL)
txt(Inches(0.95), Inches(5.12), Inches(4.85), Inches(1.1),
"Die Schattenbuchhaltung wird zum Single Point of Truth nicht Vault.",
size=19, color=WHITE, bold=True, lead=1.08, font=FC)
txt(Inches(0.95), Inches(6.45), Inches(4.85), Inches(0.4),
"Genau die Rolle, die Vault halten müsste.", size=13.5, color=LIGHT, italic=True)
# ===========================================================================
# RECHTS: Kette Auftrag -> Auftragsannahme -> SPOT -> Vault -> Zusammenführung
# ===========================================================================
fx, fy, fw, fh = Inches(6.25), Inches(2.1), Inches(5.9), Inches(4.72)
panel = shp(MSO_SHAPE.ROUNDED_RECTANGLE, fx, fy, fw, fh, fill=WHITE)
alpha(panel, 10)
panel.line.color.rgb = WHITE; panel.line.width = Pt(1)
line_alpha(panel, 35)
txt(fx + Inches(0.3), fy + Inches(0.12), fw - Inches(0.6), Inches(0.3),
"Auftragsweg hin und zurück durch den Layer", size=12.5, color=WHITE, bold=True)
cxc = fx + Inches(2.05)
bw = Inches(2.7)
bx = cxc - bw / 2
def down(y, label=None):
shp(MSO_SHAPE.DOWN_ARROW, cxc - Inches(0.11), y, Inches(0.22), Inches(0.22), fill=LIGHT)
if label:
txt(cxc + Inches(0.22), y - Inches(0.02), Inches(1.7), Inches(0.3), label,
size=11, color=LIGHT, italic=True, anchor=MSO_ANCHOR.MIDDLE)
# 1) Auftrag
b = shp(MSO_SHAPE.ROUNDED_RECTANGLE, bx, fy + Inches(0.44), bw, Inches(0.40), fill=WHITE)
boxtext(b, "Auftrag · Mischauftrag", size=12.5, color=INK, bold=True)
down(fy + Inches(0.86))
# 2) Auftragsannahme (ersetzt altes LIS)
b = shp(MSO_SHAPE.ROUNDED_RECTANGLE, bx, fy + Inches(1.06), bw, Inches(0.40), fill=WHITE)
boxtext(b, "Auftragsannahme", size=13, color=INK, bold=True)
down(fy + Inches(1.48), "Magic")
# 3) Schattenbuchhaltung = Rahmen um den Vault-Kasten
frx, fry = bx - Inches(0.22), fy + Inches(1.72)
frw, frh = bw + Inches(0.50), Inches(2.22)
frame = shp(MSO_SHAPE.ROUNDED_RECTANGLE, frx, fry, frw, frh,
fill=RGBColor(0xFF, 0xE3, 0x9B))
alpha(frame, 22)
frame.line.color.rgb = CORAL; frame.line.width = Pt(2)
# Überschrift + Positions-Mapping (oben im Rahmen)
txt(frx, fy + Inches(1.78), frw, Inches(0.28), "Schattenbuchhaltung",
size=13, color=CORAL, bold=True, align=PP_ALIGN.CENTER)
txt(frx, fy + Inches(2.07), frw, Inches(0.24), "Positions-Mapping",
size=11.5, color=WHITE, align=PP_ALIGN.CENTER)
# aktiver SPOT-Stern (rechts neben dem Rahmen)
shp(MSO_SHAPE.STAR_5_POINT, Inches(10.75), fy + Inches(1.80), Inches(0.5), Inches(0.5), fill=CORAL)
txt(Inches(9.95), fy + Inches(2.32), Inches(2.1), Inches(0.28), "Single Point of Truth",
size=10.5, color=CORAL, bold=True, align=PP_ALIGN.CENTER)
down(fy + Inches(2.33))
# 4) Vault speichert (aufgesplittet) im Rahmen
b = shp(MSO_SHAPE.ROUNDED_RECTANGLE, bx, fy + Inches(2.50), bw, Inches(0.70), fill=WHITE)
txt(bx, fy + Inches(2.55), bw, Inches(0.3), "Vault · 1:1 · Speicher",
size=13, color=INK, bold=True, align=PP_ALIGN.CENTER)
for k in range(3):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, cxc - Inches(1.08) + k * Inches(0.78),
fy + Inches(2.87), Inches(0.62), Inches(0.3), fill=RECF)
txt(cxc - Inches(1.08) + k * Inches(0.78), fy + Inches(2.87), Inches(0.62), Inches(0.3),
"Rec", size=9.5, color=INK, align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
# Geist-Stern (durchgestrichen) die Wahrheit müsste hier liegen
gx = Inches(10.79)
gs = shp(MSO_SHAPE.STAR_5_POINT, gx, fy + Inches(2.55), Inches(0.42), Inches(0.42))
gs.fill.background(); gs.line.color.rgb = LIGHT; gs.line.width = Pt(1.25)
shp(MSO_SHAPE.RECTANGLE, gx - Inches(0.02), fy + Inches(2.73), Inches(0.46), Pt(2),
fill=CORAL, rot=20)
txt(Inches(9.95), fy + Inches(3.02), Inches(2.1), Inches(0.3), "müsste hier liegen",
size=10, color=LIGHT, align=PP_ALIGN.CENTER)
down(fy + Inches(3.22))
# 5) Daten zusammenführen (unten im Rahmen)
txt(frx, fy + Inches(3.42), frw, Inches(0.28), "Daten Zusammenführen",
size=12.5, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
# 6) Weiterverarbeitung grauer Pfeil + weißer Kasten unter dem Rahmen
shp(MSO_SHAPE.DOWN_ARROW, cxc - Inches(0.11), fy + Inches(4.00), Inches(0.22), Inches(0.22),
fill=RGBColor(0x8C, 0x8C, 0x8C))
b = shp(MSO_SHAPE.ROUNDED_RECTANGLE, bx, fy + Inches(4.26), bw, Inches(0.40), fill=WHITE)
boxtext(b, "Weiterverarbeitung", size=12.5, color=INK, bold=True)
# Rückweg (Lesen) Pfeil links nach oben, Label vertikal daneben
ua = shp(MSO_SHAPE.UP_ARROW, fx + Inches(0.08), fy + Inches(1.55), Inches(0.26), Inches(2.30),
fill=LIGHT)
alpha(ua, 55)
lt = s.shapes.add_textbox(fx - Inches(0.95), fy + Inches(2.40), Inches(2.2), Inches(0.3))
ltf = lt.text_frame; ltf.word_wrap = False
ltf.margin_left = ltf.margin_right = ltf.margin_top = ltf.margin_bottom = Pt(0)
lp = ltf.paragraphs[0]; lp.alignment = PP_ALIGN.CENTER
lr = lp.add_run(); lr.text = "Lesen: zurück durch den Layer"
lr.font.size = Pt(9.5); lr.font.name = F; lr.font.color.rgb = CORAL
lt.rotation = 270
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie2.pptx")
prs.save(out)
print("saved", out)
+283
View File
@@ -0,0 +1,283 @@
#!/usr/bin/env python3
"""Folie 3 LIS mit Umsystemen (Adapter, links/rechts) und andockenden Modulen
(unten), unter einer Steuerungs-/Governance-Schicht; weitere LIS angedeutet."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, MUTE, RECF,
F, FC, paint_background, chrome)
# Rollen-Mapping auf die adesso-Palette
NAVY = INK # dunkle Strukturelemente (Bar, LIS-Kern)
ACCENT = CORAL # Adapter-Linien
AMBER = GREEN # zweites Modul
LINEC = LIGHT # Verbinder / feine Linien
HINT = RGBColor(0xE6, 0xEF, 0xF8) # helle "weitere LIS"-Karten
HINTL = RGBColor(0xC4, 0xD6, 0xE8)
TINT_T = WHITE # Modul-Boxen weiß
TINT_A = WHITE
UMS = WHITE # Umsystem-Boxen weiß
BG = WHITE
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
s = prs.slides.add_slide(prs.slide_layouts[6])
paint_background(s, prs.slide_width, prs.slide_height)
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), rot=0):
sh = s.shapes.add_shape(kind, x, y, w, h)
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if rot: sh.rotation = rot
sh.shadow.inherit = False
return sh
def boxtext(sh, t, size=14, color=INK, bold=False):
tf = sh.text_frame; tf.word_wrap = True
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_left = tf.margin_right = Pt(3); tf.margin_top = tf.margin_bottom = Pt(1)
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.name = F; r.font.color.rgb = color
def txt(x, y, w, h, t, size=14, color=INK, bold=False, italic=False,
align=PP_ALIGN.LEFT, spc=None):
tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.name = F; r.font.color.rgb = color
if spc: r.font._rPr.set('spc', str(spc))
return tb
def hline(x, y, w, color=LINEC, weight=Pt(1.4)):
shp(MSO_SHAPE.RECTANGLE, x, y - weight / 2, w, weight, fill=color)
def vline(x, y, h, color=LINEC, weight=Pt(1.4)):
shp(MSO_SHAPE.RECTANGLE, x - weight / 2, y, weight, h, fill=color)
# ---- Kopf ------------------------------------------------------------------
chrome(s, "Offen und gesteuert", 3)
x0, x1 = Inches(0.95), Inches(12.38)
# ===========================================================================
# GOVERNANCE Icon-Karten + Strich
# ===========================================================================
def card(cx, label):
cw_, ch_ = Inches(2.05), Inches(1.25)
x, y = cx - cw_ / 2, Inches(1.5)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, cw_, ch_, fill=BG, line=LINEC, lw=Pt(1.25))
txt(x, y + ch_ - Inches(0.4), cw_, Inches(0.34), label,
size=14, color=NAVY, bold=True, align=PP_ALIGN.CENTER)
return cx, y + Inches(0.42)
def regler(cx, cy):
tw = Inches(0.62)
left = cx - tw / 2
for j, frac in enumerate([0.30, 0.68, 0.48]):
ty = cy - Inches(0.18) + j * Inches(0.18)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, left, ty - Inches(0.022), tw, Inches(0.045), fill=LINEC)
kx = left + Inches(0.62 * frac)
shp(MSO_SHAPE.OVAL, kx - Inches(0.07), ty - Inches(0.07),
Inches(0.14), Inches(0.14), fill=NAVY)
cx1, cy1 = card(Inches(4.75), "Steuerung")
cx2, cy2 = card(Inches(6.95), "Reporting")
cx3, cy3 = card(Inches(9.15), "Governance")
regler(cx1, cy1)
# Reporting Zahlenreihen
nb = s.shapes.add_textbox(cx2 - Inches(0.85), cy2 - Inches(0.36), Inches(1.7), Inches(0.72))
tf = nb.text_frame; tf.word_wrap = False; tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
for i, row in enumerate(["3 8 1 4 7", "6 0 9 2 5", "5 7 2 8 1"]):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
p.alignment = PP_ALIGN.CENTER; p.line_spacing = 0.95
r = p.add_run(); r.text = row
r.font.size = Pt(11); r.font.name = "Consolas"; r.font.color.rgb = MUTE
# Governance §
gtb = s.shapes.add_textbox(cx3 - Inches(0.6), cy3 - Inches(0.42), Inches(1.2), Inches(0.8))
gtf = gtb.text_frame; gtf.vertical_anchor = MSO_ANCHOR.MIDDLE
gp = gtf.paragraphs[0]; gp.alignment = PP_ALIGN.CENTER
gr = gp.add_run(); gr.text = "§"; gr.font.size = Pt(34); gr.font.bold = True
gr.font.name = F; gr.font.color.rgb = NAVY
gov_y = Inches(3.05)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x0, gov_y - Inches(0.07), x1 - x0, Inches(0.14), fill=NAVY)
for cc in (cx1, cx2, cx3):
vline(cc, Inches(2.75), gov_y - Inches(0.07) - Inches(2.75), color=LINEC, weight=Pt(1))
# ===========================================================================
# LIS + Umsysteme (Adapter links/rechts) + Module (andocken, unten)
# ===========================================================================
core_x, core_w = Inches(3.7), Inches(2.3)
core_y, core_h = Inches(4.3), Inches(1.2)
core_cx = core_x + core_w / 2
core_by = core_y + core_h
# Adapter-Schicht: echte Schicht als Hülle um den Kern (Trennung)
lay_pad_x, lay_pad_t = Inches(0.24), Inches(0.30)
lay_x = core_x - lay_pad_x
lay_w = core_w + lay_pad_x * 2
lay_y = core_y - lay_pad_t
lay_h = core_h + lay_pad_t
lay_right = lay_x + lay_w
def adapter(xc, yc):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, xc - Inches(0.10), yc - Inches(0.11),
Inches(0.16), Inches(0.22), fill=ACCENT)
shp(MSO_SHAPE.RECTANGLE, xc + Inches(0.06), yc - Inches(0.055), Inches(0.1), Pt(2.4), fill=ACCENT)
shp(MSO_SHAPE.RECTANGLE, xc + Inches(0.06), yc + Inches(0.03), Inches(0.1), Pt(2.4), fill=ACCENT)
def dock(xc, yc):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, xc - Inches(0.1), yc - Inches(0.1),
Inches(0.2), Inches(0.2), fill=NAVY)
shp(MSO_SHAPE.OVAL, xc - Inches(0.055), yc - Inches(0.055), Inches(0.11), Inches(0.11),
fill=ACCENT)
def icon_truck(ix, iy): # Anlieferung
shp(MSO_SHAPE.ROUNDED_RECTANGLE, ix - Inches(0.20), iy - Inches(0.10),
Inches(0.24), Inches(0.16), fill=NAVY)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, ix + Inches(0.05), iy - Inches(0.035),
Inches(0.12), Inches(0.095), fill=NAVY)
for wx in (ix - Inches(0.11), ix + Inches(0.08)):
shp(MSO_SHAPE.OVAL, wx - Inches(0.038), iy + Inches(0.05),
Inches(0.076), Inches(0.076), fill=NAVY)
def icon_device(ix, iy): # Gerät
shp(MSO_SHAPE.ROUNDED_RECTANGLE, ix - Inches(0.16), iy - Inches(0.14),
Inches(0.32), Inches(0.28), fill=NAVY)
shp(MSO_SHAPE.RECTANGLE, ix - Inches(0.11), iy - Inches(0.10),
Inches(0.22), Inches(0.085), fill=RGBColor(0x34, 0x4E, 0x70))
shp(MSO_SHAPE.OVAL, ix - Inches(0.085), iy + Inches(0.03), Inches(0.055), Inches(0.055), fill=TEAL)
shp(MSO_SHAPE.OVAL, ix + Inches(0.03), iy + Inches(0.03), Inches(0.055), Inches(0.055), fill=AMBER)
def icon_dfu(ix, iy): # DFÜ
shp(MSO_SHAPE.RIGHT_ARROW, ix - Inches(0.16), iy - Inches(0.12), Inches(0.32), Inches(0.095),
fill=NAVY)
shp(MSO_SHAPE.LEFT_ARROW, ix - Inches(0.16), iy + Inches(0.025), Inches(0.32), Inches(0.095),
fill=ACCENT)
g = Inches(0.10) # Abstand Adapter-Linie <-> LIS
th = Inches(0.08) # Dicke der roten Adapter-Linie
# Governance -> obere Adapter-Linie am Kern
vline(core_cx, gov_y + Inches(0.07), (core_y - g - th) - (gov_y + Inches(0.07)),
color=LINEC, weight=Pt(1))
uw, uh = Inches(1.55), Inches(0.6)
def ums_box(bx, yc, name, icon_fn):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, bx, yc - uh / 2, uw, uh, fill=UMS, line=LINEC)
icon_fn(bx + Inches(0.32), yc)
txt(bx + Inches(0.58), yc - Inches(0.16), uw - Inches(0.64), Inches(0.32), name,
size=12, color=INK, align=PP_ALIGN.LEFT)
# Umsysteme links -> Adapter-Schichten am linken Kernrand
lx = Inches(0.8)
ums_box(lx, Inches(4.6), "Anlieferung", icon_truck)
ums_box(lx, Inches(5.2), "DFÜ", icon_dfu)
for yc in (Inches(4.6), Inches(5.2)):
hline(lx + uw, yc, (core_x - g - th) - (lx + uw))
# Umsystem rechts -> Adapter-Linie am rechten Kernrand
gx = Inches(6.65)
ums_box(gx, Inches(4.9), "Geräte", icon_device)
hline(core_x + core_w + g + th, Inches(4.9), gx - (core_x + core_w + g + th))
# ---- LIS-Kern -------------------------------------------------------------
shp(MSO_SHAPE.ROUNDED_RECTANGLE, core_x, core_y, core_w, core_h, fill=NAVY)
sh = shp(MSO_SHAPE.ROUNDED_RECTANGLE, core_x, core_y, core_w, core_h, fill=NAVY)
boxtext(sh, "LIS", size=22, color=WHITE, bold=True)
# ---- 5 Adapter-Linien je Schnittstelle eine, mit Abstand zum Kern -------
def rbar_v(outer_x, yc, h=Inches(0.55)): # vertikal, linker/rechter Rand
shp(MSO_SHAPE.RECTANGLE, outer_x, yc - h / 2, th, h, fill=ACCENT)
def rbar_h(xc, outer_y, w): # horizontal, oben/unten
shp(MSO_SHAPE.RECTANGLE, xc - w / 2, outer_y, w, th, fill=ACCENT)
rbar_v(core_x - g - th, Inches(4.6)) # 1) Anlieferung
rbar_v(core_x - g - th, Inches(5.2)) # 2) DFÜ
rbar_h(core_cx, core_y - g - th, Inches(1.15)) # 3) nach oben (Steuerung)
rbar_v(core_x + core_w + g, Inches(4.9)) # 4) Geräte
rbar_h(core_cx, core_by + g, core_w - Inches(0.2)) # 5) Fachliche Verarbeitung
# Fachliche Verarbeitung (unten): Module an der unteren Adapter-Linie
mw, mh = Inches(1.7), Inches(0.6)
my = Inches(6.05)
for nm, fill, tc, mcx in [("Hochdurchsatz", TINT_T, TEAL, Inches(3.85)),
("Spezial", TINT_A, AMBER, Inches(5.85))]:
vline(mcx, core_by + g + th, my - (core_by + g + th), color=LINEC, weight=Pt(1))
sh = shp(MSO_SHAPE.ROUNDED_RECTANGLE, mcx - mw / 2, my, mw, mh, fill=fill, line=tc, lw=Pt(1.5))
boxtext(sh, nm, size=12.5, color=INK, bold=True)
txt(Inches(2.9), my + mh + Inches(0.12), Inches(4.0), Inches(0.3), "Fachliche Verarbeitung",
size=12, color=LIGHT, bold=True, align=PP_ALIGN.CENTER)
# ===========================================================================
# WEITERE LIS überlappend, nur angedeutet
# ===========================================================================
hw_, hh_ = Inches(1.8), Inches(2.0)
def mini_lis(hx, hy, faded=False):
fill = RGBColor(0xF4, 0xF6, 0xF8) if faded else HINT
shp(MSO_SHAPE.ROUNDED_RECTANGLE, hx, hy, hw_, hh_, fill=fill, line=HINTL, lw=Pt(1.25))
hdc = shp(MSO_SHAPE.ROUNDED_RECTANGLE, hx, hy, hw_, Inches(0.46),
fill=HINTL if not faded else RGBColor(0xDF, 0xE4, 0xEA))
boxtext(hdc, "LIS", size=14, color=NAVY, bold=True)
for k in range(3):
yy = hy + Inches(0.66) + k * Inches(0.4)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, hx + Inches(0.2), yy, hw_ - Inches(0.4),
Inches(0.28), fill=WHITE, line=HINTL, lw=Pt(0.75))
mini_lis(Inches(10.5), Inches(4.35), faded=True)
mini_lis(Inches(10.0), Inches(4.75), faded=False)
vline(Inches(10.0) + hw_ / 2, gov_y + Inches(0.07), Inches(4.75) - (gov_y + Inches(0.07)),
color=LINEC, weight=Pt(1))
txt(Inches(9.9), Inches(4.35) + hh_ + Inches(0.2), Inches(2.4), Inches(0.35), "weitere LIS",
size=13, color=LIGHT, align=PP_ALIGN.CENTER)
# ---- Mini-Legende ----------------------------------------------------------
ly = Inches(7.05)
shp(MSO_SHAPE.RECTANGLE, Inches(7.55), ly - Inches(0.11), th, Inches(0.22), fill=ACCENT)
txt(Inches(7.8), ly - Inches(0.16), Inches(3.2), Inches(0.32),
"Adapter-Schicht je Schnittstelle eine", size=11.5, color=LIGHT)
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie3.pptx")
prs.save(out)
print("saved", out)
+180
View File
@@ -0,0 +1,180 @@
#!/usr/bin/env python3
"""Folie 4 (eingehängt nach Folie 3) Architektur der Modularisierung:
Modularer Monolith vs. Microservices, anschaulich im Containerumfeld.
Links: 1 Container, Module mit In-Process-Calls, 1 geteilte DB.
Rechts: N Container, Services über Netzwerk, DB je Service.
Unten: kompakte Gegenüberstellung der wesentlichen Unterschiede."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, MUTE, RECF,
F, FC, paint_background, chrome)
NAVY = INK
ACCENT = CORAL
LINEC = LIGHT
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
s = prs.slides.add_slide(prs.slide_layouts[6])
paint_background(s, prs.slide_width, prs.slide_height)
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), rot=0):
sh = s.shapes.add_shape(kind, x, y, w, h)
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if rot: sh.rotation = rot
sh.shadow.inherit = False
return sh
def boxtext(sh, t, size=14, color=INK, bold=False):
tf = sh.text_frame; tf.word_wrap = True
tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_left = tf.margin_right = Pt(3); tf.margin_top = tf.margin_bottom = Pt(1)
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.name = F; r.font.color.rgb = color
def txt(x, y, w, h, t, size=14, color=INK, bold=False, italic=False,
align=PP_ALIGN.LEFT, spc=None):
tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.name = F; r.font.color.rgb = color
if spc: r.font._rPr.set('spc', str(spc))
return tb
def vline(x, y, h, color=LINEC, weight=Pt(1.4)):
shp(MSO_SHAPE.RECTANGLE, x - weight / 2, y, weight, h, fill=color)
def hline(x, y, w, color=LINEC, weight=Pt(1.4)):
shp(MSO_SHAPE.RECTANGLE, x, y - weight / 2, w, weight, fill=color)
# ---- Kopf + Kernaussage ----------------------------------------------------
chrome(s, "Architektur der Modularisierung", 4)
txt(Inches(1.25), Inches(0.98), Inches(11.6), Inches(0.34),
"Gleiche fachlichen Schnitte der Unterschied ist die Laufzeit- und Deployment-Grenze.",
size=14, color=LIGHT, italic=True)
DOT = [TEAL, GREEN, BLUE] # gleiche Module/Services beidseitig farblich verankert
LET = ["A", "B", "C"]
# ===========================================================================
# Spalten-Titel
# ===========================================================================
cL = Inches(3.6) # Mittelpunkt linke Spalte
cR = Inches(9.75) # Mittelpunkt rechte Spalte
txt(Inches(0.95), Inches(1.5), Inches(5.3), Inches(0.32), "Modularer Monolith",
size=18, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
txt(Inches(0.95), Inches(1.84), Inches(5.3), Inches(0.26), "1 Deployable · 1 Prozess",
size=11.5, color=LIGHT, align=PP_ALIGN.CENTER)
txt(Inches(7.0), Inches(1.5), Inches(5.5), Inches(0.32), "Microservices",
size=18, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
txt(Inches(7.0), Inches(1.84), Inches(5.5), Inches(0.26), "N Deployables · N Prozesse",
size=11.5, color=LIGHT, align=PP_ALIGN.CENTER)
# ===========================================================================
# LINKS Modularer Monolith: 1 Container, Module, geteilte DB
# ===========================================================================
cx_x, cx_w, cx_y, cx_h = Inches(0.95), Inches(5.3), Inches(2.2), Inches(1.6)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, cx_x, cx_y, cx_w, cx_h, line=WHITE, lw=Pt(1.5))
txt(cx_x + Inches(0.15), cx_y + Inches(0.05), Inches(2.0), Inches(0.26), "1 Container",
size=11, color=LIGHT, bold=True)
mw, mh, my = Inches(1.35), Inches(0.8), Inches(2.62)
mcx = [Inches(2.05), Inches(3.6), Inches(5.15)]
for i, mx in enumerate(mcx):
sh = shp(MSO_SHAPE.ROUNDED_RECTANGLE, mx - mw / 2, my, mw, mh, fill=WHITE, line=LINEC, lw=Pt(1))
boxtext(sh, "Modul " + LET[i], size=13, color=INK, bold=True)
shp(MSO_SHAPE.OVAL, mx - Inches(0.07), my + Inches(0.12), Inches(0.14), Inches(0.14), fill=DOT[i])
# In-Process-Pfeile zwischen den Modulen
for ax in (Inches(2.725), Inches(4.275)):
shp(MSO_SHAPE.RIGHT_ARROW, ax, my + mh / 2 - Inches(0.09), Inches(0.2), Inches(0.18), fill=ACCENT)
txt(cx_x, cx_y + cx_h - Inches(0.34), cx_w, Inches(0.26), "In-Process-Aufrufe · Nanosekunden",
size=11, color=LIGHT, align=PP_ALIGN.CENTER)
# geteilte Datenbank
db_w, db_h, db_y = Inches(1.5), Inches(0.95), Inches(4.0)
vline(cL, cx_y + cx_h, db_y - (cx_y + cx_h), color=LINEC, weight=Pt(1.4))
sh = shp(MSO_SHAPE.CAN, cL - db_w / 2, db_y, db_w, db_h, fill=WHITE, line=LINEC, lw=Pt(1))
boxtext(sh, "DB", size=14, color=INK, bold=True)
txt(cx_x, db_y + db_h + Inches(0.06), cx_w, Inches(0.28), "1 geteilte Datenbank",
size=12.5, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
# ===========================================================================
# RECHTS Microservices: Netzwerk-Bus, N Container, DB je Service
# ===========================================================================
bar_x, bar_w, bar_y, bar_h = Inches(7.1), Inches(5.3), Inches(2.2), Inches(0.26)
bar = shp(MSO_SHAPE.ROUNDED_RECTANGLE, bar_x, bar_y, bar_w, bar_h, fill=NAVY)
boxtext(bar, "Netzwerk-Grenze · HTTP / gRPC / Events", size=11, color=WHITE, bold=True)
scx = [Inches(7.95), Inches(9.75), Inches(11.55)]
sc_w, sc_h, sc_y = Inches(1.5), Inches(1.2), Inches(2.62)
sdb_w, sdb_h, sdb_y = Inches(0.85), Inches(0.7), Inches(3.97)
for i, cx in enumerate(scx):
vline(cx, bar_y + bar_h, sc_y - (bar_y + bar_h), color=LINEC, weight=Pt(1.1))
shp(MSO_SHAPE.ROUNDED_RECTANGLE, cx - sc_w / 2, sc_y, sc_w, sc_h, line=WHITE, lw=Pt(1.5))
sh = shp(MSO_SHAPE.ROUNDED_RECTANGLE, cx - Inches(0.55), sc_y + Inches(0.3),
Inches(1.1), Inches(0.62), fill=WHITE, line=LINEC, lw=Pt(1))
boxtext(sh, "Svc " + LET[i], size=12.5, color=INK, bold=True)
shp(MSO_SHAPE.OVAL, cx - Inches(0.06), sc_y + Inches(0.4), Inches(0.12), Inches(0.12), fill=DOT[i])
# eigene DB je Service
vline(cx, sc_y + sc_h, sdb_y - (sc_y + sc_h), color=LINEC, weight=Pt(1.1))
sh = shp(MSO_SHAPE.CAN, cx - sdb_w / 2, sdb_y, sdb_w, sdb_h, fill=WHITE, line=LINEC, lw=Pt(1))
boxtext(sh, "DB", size=11, color=INK, bold=True)
txt(bar_x, sdb_y + sdb_h + Inches(0.06), bar_w, Inches(0.28), "Datenbank je Service",
size=12.5, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
# ===========================================================================
# Trenner + vs.
# ===========================================================================
vline(Inches(6.65), Inches(1.55), Inches(3.5), color=LINEC, weight=Pt(1))
vs = shp(MSO_SHAPE.OVAL, Inches(6.65) - Inches(0.31), Inches(3.05), Inches(0.62), Inches(0.46),
line=WHITE, lw=Pt(1.5))
vs.fill.background()
boxtext(vs, "vs.", size=13, color=WHITE, bold=True)
# ===========================================================================
# Gegenüberstellung wesentliche Unterschiede
# ===========================================================================
rows = [
("Skalierung", "als Ganzes (mehr Replicas)", "je Service gezielt"),
("Datenhaltung", "1 geteilte DB", "DB je Service"),
("Deployment", "gemeinsam, 1 Pipeline", "unabhängig je Service"),
("Konsistenz", "ACID, lokal", "eventual / Saga"),
]
ry = Inches(5.5)
rh = Inches(0.33)
chip_w = Inches(1.95)
for i, (dim, mono, ms) in enumerate(rows):
y = ry + rh * i
chip = shp(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(6.65) - chip_w / 2, y, chip_w, Inches(0.28),
line=LINEC, lw=Pt(0.75))
chip.fill.background()
boxtext(chip, dim, size=11, color=LIGHT, bold=True)
txt(Inches(2.5), y - Inches(0.02), Inches(3.1), Inches(0.32), mono,
size=12, color=WHITE, align=PP_ALIGN.RIGHT)
txt(Inches(7.72), y - Inches(0.02), Inches(3.1), Inches(0.32), ms,
size=12, color=WHITE, align=PP_ALIGN.LEFT)
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie3b.pptx")
prs.save(out)
print("saved", out)
+161
View File
@@ -0,0 +1,161 @@
#!/usr/bin/env python3
"""Folie 4 Eventstream als Quelle; Aussagen links, Lupen rechts, Strecke unten
(adesso-Styling)."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, RECF, F, FC,
paint_background, chrome)
# Rollen-Mapping auf die adesso-Palette
NAVY = INK # dunkle Füllungen (Lupe, Maschine)
ACCENT = CORAL
AMBER = GREEN
GLASS = RECF
BELT = RECF
DARK = INK
LINEC = LIGHT
THIN = LIGHT
STREAM = INK
MID = RGBColor(0x34, 0x4E, 0x70)
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
s = prs.slides.add_slide(prs.slide_layouts[6])
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), rot=0):
sh = s.shapes.add_shape(kind, x, y, w, h)
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if rot: sh.rotation = rot
sh.shadow.inherit = False
return sh
def txt(x, y, w, h, t, size=16, color=WHITE, bold=False, italic=False,
align=PP_ALIGN.LEFT, spc=None, font=F):
tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.name = font; r.font.color.rgb = color
if spc: r.font._rPr.set('spc', str(spc))
return tb
paint_background(s, SW, SH)
chrome(s, "Zustand oder Ereignis", 5)
x0, x1 = Inches(1.0), Inches(12.33)
beltw = x1 - x0
# ---- Aussagen links --------------------------------------------------------
claims = [
"Eventstream = einzige Quelle der Wahrheit",
"kann nicht überschrieben werden",
"vollständige 3D-Sicht auf Maschine / Strang",
]
cy = Inches(1.95)
for i, c in enumerate(claims):
y = cy + Inches(0.6) * i
shp(MSO_SHAPE.RECTANGLE, Inches(0.95), y + Inches(0.1), Inches(0.14), Inches(0.14), fill=ACCENT)
txt(Inches(1.28), y, Inches(4.6), Inches(0.45), c, size=16.5, color=WHITE, bold=(i == 0))
# ===========================================================================
# LUPEN (Projektionen)
# ===========================================================================
def lupe(cx, label, label_w):
cyy = Inches(2.45)
d = Inches(0.9)
shp(MSO_SHAPE.OVAL, cx - d / 2, cyy - d / 2, d, d, fill=WHITE, line=NAVY, lw=Pt(4))
shp(MSO_SHAPE.OVAL, cx - d / 2 + Inches(0.13), cyy - d / 2 + Inches(0.12),
Inches(0.17), Inches(0.13), fill=RECF)
hw, hh = Inches(0.48), Inches(0.15)
hcx, hcy = cx + d * 0.52, cyy + d * 0.52
shp(MSO_SHAPE.ROUNDED_RECTANGLE, hcx - hw / 2, hcy - hh / 2, hw, hh, fill=NAVY, rot=45)
txt(cx - label_w / 2, cyy + d / 2 + Inches(0.16), label_w, Inches(0.6),
label, size=14, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
return cyy + d / 2
lupes = [
(Inches(7.05), "Gruppen-Reporting", Inches(2.3)),
(Inches(9.45), "Optimierung der Auslastung", Inches(2.3)),
(Inches(11.55), "Abrechnungen", Inches(1.9)),
]
lens_bottoms = [lupe(cx, lb, lw) for cx, lb, lw in lupes]
# ===========================================================================
# EVENTSTREAM (Pfeil)
# ===========================================================================
ay, ah = Inches(4.45), Inches(0.46)
shp(MSO_SHAPE.RIGHT_ARROW, x0, ay, beltw, ah, fill=STREAM)
acx = ay + ah / 2
txt(Inches(5.65), ay + Inches(0.04), Inches(2.0), ah - Inches(0.08),
"Eventstream", size=14, color=WHITE, bold=True, align=PP_ALIGN.CENTER)
# Verbinder Lupe -> Strom
for (cx, _, _), lb_y in zip(lupes, lens_bottoms):
shp(MSO_SHAPE.RECTANGLE, cx - Pt(0.5), lb_y, Pt(1), ay - lb_y, fill=LINEC)
# ===========================================================================
# RÖHRCHEN-STRECKE durch Maschine unten
# ===========================================================================
belt_top = Inches(6.1)
belt_h = Inches(0.30)
for rx in (x0 - Inches(0.18), x1 - Inches(0.32)):
shp(MSO_SHAPE.OVAL, rx, belt_top - Inches(0.10), Inches(0.5), Inches(0.5),
fill=BELT, line=LINEC)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x0, belt_top, beltw, belt_h, fill=BELT)
mx, mw = Inches(5.45), Inches(2.45)
my, mh = Inches(5.2), Inches(1.5)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, mx, my, mw, mh, fill=NAVY)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, mx + Inches(0.3), my + Inches(0.22),
mw - Inches(0.6), Inches(0.32), fill=MID)
shp(MSO_SHAPE.OVAL, mx + Inches(0.35), my + Inches(0.74), Inches(0.15), Inches(0.15), fill=TEAL)
shp(MSO_SHAPE.OVAL, mx + Inches(0.6), my + Inches(0.74), Inches(0.15), Inches(0.15), fill=AMBER)
shp(MSO_SHAPE.RECTANGLE, mx - Inches(0.02), belt_top - Inches(0.02),
Inches(0.14), belt_h + Inches(0.04), fill=DARK)
shp(MSO_SHAPE.RECTANGLE, mx + mw - Inches(0.12), belt_top - Inches(0.02),
Inches(0.14), belt_h + Inches(0.04), fill=DARK)
def tube(cx, liquid):
bw, bh = Inches(0.22), Inches(0.6)
bx, by = cx - bw / 2, belt_top - bh
shp(MSO_SHAPE.ROUNDED_RECTANGLE, bx, by, bw, bh, fill=GLASS, line=LINEC, lw=Pt(0.75))
lh = Inches(0.25)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, bx + Pt(1), belt_top - lh, bw - Pt(2), lh, fill=liquid)
cw, ch = Inches(0.26), Inches(0.12)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, cx - cw / 2, by - Inches(0.06), cw, ch, fill=DARK)
cols = [ACCENT, TEAL, AMBER]
pre_x = [1.55, 2.1, 2.65, 3.2, 3.75, 4.3, 4.85]
post_x = [8.25, 8.8, 9.35, 9.9, 10.45, 11.0]
for i, xv in enumerate(pre_x + post_x):
tube(Inches(xv), cols[i % 3])
tube_top = belt_top - Inches(0.6)
for xv in pre_x + post_x:
shp(MSO_SHAPE.RECTANGLE, Inches(xv) - Pt(0.4), ay + ah,
Pt(0.8), tube_top - (ay + ah), fill=THIN)
shp(MSO_SHAPE.OVAL, Inches(xv) - Inches(0.05), acx - Inches(0.05),
Inches(0.1), Inches(0.1), fill=AMBER)
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie4.pptx")
prs.save(out)
print("saved", out)
+177
View File
@@ -0,0 +1,177 @@
#!/usr/bin/env python3
"""Folie 5 Event Sourcing: das groessere Bild (DEUTSCH).
Quellen differenziert (Publisher / Subsysteme), Event-Prozessoren als Teil des Stores,
Hot Store & Cold Store als Kernfunktion (Coral, CORE-Tag), Projektionen dazwischen,
darunter Cold Store / Monitoring / Reporting. Tech-Impls als Chips. (adesso-Styling)
Hintergrund: solides dunkles Blau (BG) Farbe frei anpassbar."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, MUTE, RECF,
F, FC, chrome)
# ---- Hintergrundfarbe (solid, keine Transparenz) frei anpassbar ----------
BG = RGBColor(0x0A, 0x3D, 0x6B) # dunkles Blau
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
s = prs.slides.add_slide(prs.slide_layouts[6])
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), rot=0, adj=None):
sh = s.shapes.add_shape(kind, x, y, w, h)
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if rot: sh.rotation = rot
if adj is not None:
try: sh.adjustments[0] = adj
except Exception: pass
sh.shadow.inherit = False
return sh
def txt(x, y, w, h, t, size=16, color=WHITE, bold=False, italic=False,
align=PP_ALIGN.LEFT, font=F, anchor=MSO_ANCHOR.MIDDLE):
tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = anchor
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
first = True
for line in t.split("\n"):
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False
p.alignment = align
r = p.add_run(); r.text = line
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.name = font; r.font.color.rgb = color
return tb
def chip(cx, y, text, fill=INK, fg=WHITE, size=11):
"""Tech-Impl als kleine Pill, zentriert um cx."""
w = Inches(0.34 + 0.092 * len(text)); h = Inches(0.30)
x = cx - w / 2
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=fill, adj=0.5)
txt(x, y, w, h, text, size=size, color=fg, bold=False,
align=PP_ALIGN.CENTER, font=FC)
def core_tag(x, y):
w, h = Inches(0.62), Inches(0.26)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=INK, adj=0.5)
txt(x, y, w, h, "CORE", size=9.5, color=TEAL, bold=True,
align=PP_ALIGN.CENTER, font=FC)
# ---- solider Hintergrund (zuerst -> liegt hinten) --------------------------
bg = shp(MSO_SHAPE.RECTANGLE, 0, 0, SW, SH, fill=BG)
chrome(s, "System Landscape", 6)
CX = Inches(6.665) # Folienmitte (x)
# ---- Quellen: differenziert ------------------------------------------------
src_y, src_h = Inches(1.36), Inches(0.92)
def source_box(x, w, title, examples):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, src_y, w, src_h, fill=WHITE, adj=0.10)
txt(x + Inches(0.28), src_y + Inches(0.10), w - Inches(0.56), Inches(0.32),
title, size=14.5, color=INK, bold=True, anchor=MSO_ANCHOR.TOP)
txt(x + Inches(0.28), src_y + Inches(0.46), w - Inches(0.56), Inches(0.36),
examples, size=12, color=MUTE, anchor=MSO_ANCHOR.TOP)
pub_x, pub_w = Inches(0.9), Inches(5.6)
sub_x, sub_w = Inches(6.83), Inches(5.6)
pub_cx = pub_x + pub_w / 2
sub_cx = sub_x + sub_w / 2
source_box(pub_x, pub_w, "Publisher (nur publizieren)",
"z. B. AB+M · LabAccess · MDN · Stammdaten — proprietär")
source_box(sub_x, sub_w, "Subsysteme (konsumieren & publizieren)",
"z. B. LIS · Geräte / Analyzer — proprietär")
# ---- Pfeile Quellen -> Hot Store ------------------------------------------
ay, ah = src_y + src_h + Inches(0.02), Inches(0.30)
shp(MSO_SHAPE.DOWN_ARROW, pub_cx - Inches(0.16), ay, Inches(0.32), ah, fill=CORAL)
txt(pub_cx + Inches(0.28), ay - Inches(0.01), Inches(1.6), ah + Inches(0.02),
"publizieren", size=11, color=LIGHT, italic=True)
shp(MSO_SHAPE.UP_DOWN_ARROW, sub_cx - Inches(0.11), ay - Inches(0.05), Inches(0.22),
ah + Inches(0.10), fill=CORAL)
txt(sub_cx - Inches(2.85), ay - Inches(0.01), Inches(2.5), ah + Inches(0.02),
"konsumieren & publizieren", size=11, color=LIGHT, italic=True, align=PP_ALIGN.RIGHT)
# ---- HOT STORE (Kern) + Event-Prozessoren (Teil des Stores) ----------------
hx, hy, hw, hh = Inches(3.4), Inches(2.62), Inches(6.53), Inches(1.50)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, hx, hy, hw, hh, fill=CORAL, line=INK, lw=Pt(3.5), adj=0.07)
core_tag(hx + Inches(0.16), hy + Inches(0.13))
txt(hx, hy + Inches(0.05), hw, Inches(0.34),
"Event Store — Hot Store", size=20, color=INK, bold=True, align=PP_ALIGN.CENTER)
txt(hx, hy + Inches(0.40), hw, Inches(0.20),
"append-only · kanonische Wahrheit", size=12.5, color=INK, align=PP_ALIGN.CENTER)
chip(CX, hy + Inches(0.62), "z. B. Kafka")
# Event-Prozessoren als eingebetteter Bestandteil des Stores
ep_x, ep_y, ep_w, ep_h = hx + Inches(0.28), hy + Inches(0.98), hw - Inches(0.56), Inches(0.44)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, ep_x, ep_y, ep_w, ep_h, fill=WHITE, adj=0.22)
txt(ep_x, ep_y, ep_w, ep_h,
"Event-Prozessoren (konsumieren & publizieren) · z. B. Proben-Routing",
size=11.5, color=INK, bold=True, align=PP_ALIGN.CENTER)
# ---- Hot -> Projektionen ---------------------------------------------------
shp(MSO_SHAPE.DOWN_ARROW, CX - Inches(0.16), hy + hh + Inches(0.03),
Inches(0.32), Inches(0.28), fill=CORAL)
# ---- PROJEKTIONEN ----------------------------------------------------------
px, py, pw, ph = Inches(3.4), Inches(4.46), Inches(6.53), Inches(0.66)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, px, py, pw, ph, fill=WHITE, adj=0.14)
txt(px + Inches(0.3), py, Inches(3.0), ph, "Projektionen", size=16, color=INK, bold=True)
chip(px + pw - Inches(2.0), py + ph / 2 - Inches(0.15), "Kafka Streams → PostgreSQL")
# ---- Verteiler (Projektionen -> 3 Bloecke) --------------------------------
boxes_y = Inches(5.34)
bw = Inches(3.7); bh = Inches(1.56)
cold_x = Inches(0.9); cold_cx = cold_x + bw / 2
mon_x = Inches(4.815); mon_cx = mon_x + bw / 2
rep_x = Inches(8.73); rep_cx = rep_x + bw / 2
bus_y = py + ph + Inches(0.10)
shp(MSO_SHAPE.RECTANGLE, CX - Pt(0.75), py + ph, Pt(1.5), bus_y - (py + ph), fill=LIGHT)
shp(MSO_SHAPE.RECTANGLE, cold_cx, bus_y, rep_cx - cold_cx, Pt(1.5), fill=LIGHT)
for cx in (cold_cx, mon_cx, rep_cx):
shp(MSO_SHAPE.DOWN_ARROW, cx - Inches(0.11), bus_y, Inches(0.22), boxes_y - bus_y,
fill=LIGHT)
def block(x, title, body, tech, core=False):
fill = CORAL if core else WHITE
line = INK if core else None
lw = Pt(3.5) if core else Pt(1)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, boxes_y, bw, bh, fill=fill, line=line, lw=lw, adj=0.07)
ty = boxes_y + (Inches(0.30) if core else Inches(0.20))
if core:
core_tag(x + Inches(0.16), boxes_y + Inches(0.16))
txt(x, ty, bw, Inches(0.42), title, size=17, color=INK, bold=True, align=PP_ALIGN.CENTER)
txt(x + Inches(0.25), ty + Inches(0.46), bw - Inches(0.5), Inches(0.5), body,
size=12.5, color=(INK if core else MUTE), align=PP_ALIGN.CENTER)
chip(x + bw / 2, boxes_y + bh - Inches(0.42), tech)
block(cold_x, "Cold Store",
"Archiv · Audit-Trail · Dokumente", "z. B. PostgreSQL", core=True)
block(mon_x, "Monitoring",
"Auftragsstatus / Auslastung", "z. B. Grafana")
block(rep_x, "Reporting",
"Bericht an Gruppe · KPIs", "z. B. Power BI")
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie5.pptx")
prs.save(out)
print("saved", out)
+172
View File
@@ -0,0 +1,172 @@
#!/usr/bin/env python3
"""Folie 6 Core / Rationale (DEUTSCH): kompakte Landscape links, Argumente als Karten rechts.
(adesso-Styling). Hintergrund: solides dunkles Blau (BG) Farbe frei anpassbar."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, MUTE, RECF,
F, FC, chrome)
# ---- Hintergrundfarbe (solid, keine Transparenz) frei anpassbar ----------
BG = RGBColor(0x0A, 0x3D, 0x6B) # dunkles Blau
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
s = prs.slides.add_slide(prs.slide_layouts[6])
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), rot=0, adj=None):
sh = s.shapes.add_shape(kind, x, y, w, h)
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if rot: sh.rotation = rot
if adj is not None:
try: sh.adjustments[0] = adj
except Exception: pass
sh.shadow.inherit = False
return sh
def txt(x, y, w, h, t, size=16, color=WHITE, bold=False, italic=False,
align=PP_ALIGN.LEFT, font=F, anchor=MSO_ANCHOR.MIDDLE, sp=None):
tb = s.shapes.add_textbox(x, y, w, h); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = anchor
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
first = True
for line in t.split("\n"):
p = tf.paragraphs[0] if first else tf.add_paragraph()
first = False
p.alignment = align
if sp is not None: p.space_after = Pt(sp)
r = p.add_run(); r.text = line
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.name = font; r.font.color.rgb = color
return tb
def chip(cx, y, text, size=10):
w = Inches(0.30 + 0.085 * len(text)); h = Inches(0.27)
x = cx - w / 2
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=INK, adj=0.5)
txt(x, y, w, h, text, size=size, color=WHITE, align=PP_ALIGN.CENTER, font=FC)
def core_tag(x, y):
w, h = Inches(0.54), Inches(0.23)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=INK, adj=0.5)
txt(x, y, w, h, "CORE", size=8.5, color=TEAL, bold=True, align=PP_ALIGN.CENTER, font=FC)
# ---- solider Hintergrund (zuerst -> liegt hinten) --------------------------
bg = shp(MSO_SHAPE.RECTANGLE, 0, 0, SW, SH, fill=BG)
chrome(s, "Warum Event Sourcing passt", 7)
# ===========================================================================
# LINKS kompakte Landscape
# ===========================================================================
LCX = Inches(3.35)
# Quellen
shp(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(0.7), Inches(1.58), Inches(5.3), Inches(0.7),
fill=WHITE, adj=0.12)
txt(Inches(0.92), Inches(1.66), Inches(4.9), Inches(0.26), "Quellen",
size=12.5, color=INK, bold=True, anchor=MSO_ANCHOR.TOP)
txt(Inches(0.92), Inches(1.94), Inches(4.9), Inches(0.28),
"Publisher (publizieren) · Subsysteme (konsumieren & publizieren)",
size=10.5, color=MUTE, anchor=MSO_ANCHOR.TOP)
shp(MSO_SHAPE.DOWN_ARROW, LCX - Inches(0.13), Inches(2.30), Inches(0.26), Inches(0.26),
fill=CORAL)
# Hot Store (CORE) inkl. Event-Prozessoren
hy, hh = Inches(2.58), Inches(0.98)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(1.35), hy, Inches(4.0), hh,
fill=CORAL, line=INK, lw=Pt(3), adj=0.08)
core_tag(Inches(1.50), hy + Inches(0.12))
txt(Inches(1.35), hy + Inches(0.08), Inches(4.0), Inches(0.34),
"Event Store — Hot Store", size=15, color=INK, bold=True, align=PP_ALIGN.CENTER)
txt(Inches(1.35), hy + Inches(0.40), Inches(4.0), Inches(0.24),
"inkl. Event-Prozessoren", size=10.5, color=INK, align=PP_ALIGN.CENTER)
chip(LCX, hy + hh - Inches(0.34), "Kafka")
shp(MSO_SHAPE.DOWN_ARROW, LCX - Inches(0.13), hy + hh + Inches(0.02),
Inches(0.26), Inches(0.24), fill=CORAL)
# Projektionen
py, ph = Inches(3.82), Inches(0.56)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, Inches(1.35), py, Inches(4.0), ph, fill=WHITE, adj=0.16)
txt(Inches(1.55), py, Inches(2.0), ph, "Projektionen", size=12.5, color=INK, bold=True)
chip(Inches(4.25), py + ph / 2 - Inches(0.135), "Kafka Streams → PostgreSQL")
# Verteiler -> 3 Bloecke
boxes_y = Inches(4.72); mbh = Inches(1.28)
mb_w = Inches(1.65)
cold_x = Inches(0.7); cold_cx = cold_x + mb_w / 2
mon_x = Inches(2.55); mon_cx = mon_x + mb_w / 2
rep_x = Inches(4.40); rep_cx = rep_x + mb_w / 2
bus_y = py + ph + Inches(0.10)
shp(MSO_SHAPE.RECTANGLE, LCX - Pt(0.75), py + ph, Pt(1.5), bus_y - (py + ph), fill=LIGHT)
shp(MSO_SHAPE.RECTANGLE, cold_cx, bus_y, rep_cx - cold_cx, Pt(1.5), fill=LIGHT)
for cx in (cold_cx, mon_cx, rep_cx):
shp(MSO_SHAPE.DOWN_ARROW, cx - Inches(0.10), bus_y, Inches(0.20), boxes_y - bus_y, fill=LIGHT)
def minibox(x, title, tech, core=False):
fill = CORAL if core else WHITE
line = INK if core else None
lw = Pt(3) if core else Pt(1)
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, boxes_y, mb_w, mbh, fill=fill, line=line, lw=lw, adj=0.10)
if core:
core_tag(x + Inches(0.12), boxes_y + Inches(0.12))
txt(x, boxes_y + (Inches(0.42) if core else Inches(0.26)), mb_w, Inches(0.5), title,
size=12, color=INK, bold=True, align=PP_ALIGN.CENTER)
chip(x + mb_w / 2, boxes_y + mbh - Inches(0.36), tech)
minibox(cold_x, "Cold\nStore", "PostgreSQL", core=True)
minibox(mon_x, "Monitoring", "Grafana")
minibox(rep_x, "Reporting", "Power BI")
# ===========================================================================
# RECHTS Argumente als Karten
# ===========================================================================
cards = [
("Bewährte Technologie",
"Erprobt in regulierten Branchen mit hohem Volumen — z. B. ING setzt auf Kafka / Event-Streaming."),
("Flexibel",
"Neues System = neuer Adapter, ohne Eingriff in den Rest. Neue Event-Folgen & Projektionen jederzeit baubar."),
("Skalierbar",
"Selbst massive Lastzunahme wird durch mehr Hardware aufgefangen — horizontal, ohne Redesign."),
("Kosteneffizient",
"Wiederverwendbare Adapter statt Punkt-zu-Punkt. Open Source auf Standard-Hardware — kein Lock-in."),
("Auditierbar & revisionssicher",
"Append-only, vollständige & manipulationssichere Historie — vollständig replay-fähig."),
("Resilient & entkoppelt",
"Systeme fallen aus und holen per Replay auf; ein Log statt N² Schnittstellen."),
]
cw, ch = Inches(3.0), Inches(1.42)
col_x = [Inches(6.55), Inches(9.8)]
row_y = [Inches(1.62), Inches(3.30), Inches(4.98)]
for i, (title, body) in enumerate(cards):
x = col_x[i % 2]; y = row_y[i // 2]
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, cw, ch, fill=WHITE, adj=0.08)
shp(MSO_SHAPE.RECTANGLE, x + Inches(0.0), y + Inches(0.14), Inches(0.11), ch - Inches(0.28),
fill=CORAL)
txt(x + Inches(0.32), y + Inches(0.15), cw - Inches(0.5), Inches(0.36), title,
size=13.5, color=INK, bold=True, anchor=MSO_ANCHOR.TOP)
txt(x + Inches(0.32), y + Inches(0.55), cw - Inches(0.52), ch - Inches(0.68), body,
size=10.5, color=MUTE, anchor=MSO_ANCHOR.TOP)
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie6.pptx")
prs.save(out)
print("saved", out)
+192
View File
@@ -0,0 +1,192 @@
#!/usr/bin/env python3
"""Folie 7 Integrationsserver / Event-Sourcing-Anbindung (DEUTSCH, adesso-Stil).
Eingaenge (Order Entry/CLAB, Probeneingang [Atras+PVT], Geraete, Middleware, MiBi/Hybase,
Stammdaten) -> Adapter-Ebene -> Event Store -> unten Event-Prozessoren, Projektionen,
Konsumenten (SinaBI, Archivierung). Hintergrund: solides dunkles Blau (BG)."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE, MSO_CONNECTOR
from pptx.oxml.ns import qn
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, MUTE, RECF,
F, FC, chrome)
BG = RGBColor(0x0A, 0x3D, 0x6B)
GRAY = RGBColor(0xAE, 0xB7, 0xC2)
ADC = RGBColor(0xCF, 0xE2, 0xF7)
SUBC = RGBColor(0x3C, 0x4A, 0x5A) # zweite Zeile dunkel & gut lesbar
prs = Presentation(); prs.slide_width = Inches(13.333); prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
s = prs.slides.add_slide(prs.slide_layouts[6])
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), adj=None):
sh = s.shapes.add_shape(kind, Inches(x), Inches(y), Inches(w), Inches(h))
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if adj is not None:
try: sh.adjustments[0] = adj
except Exception: pass
sh.shadow.inherit = False
return sh
def txt(x, y, w, h, t, size=11, color=WHITE, bold=False, italic=False,
align=PP_ALIGN.LEFT, font=F, anchor=MSO_ANCHOR.MIDDLE):
tb = s.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h)); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = anchor
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
first = True
for line in t.split("\n"):
p = tf.paragraphs[0] if first else tf.add_paragraph(); first = False
p.alignment = align
r = p.add_run(); r.text = line
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.name = font; r.font.color.rgb = color
return tb
def conn(x1, y1, x2, y2, color=LIGHT, w=1.6, both=False):
c = s.shapes.add_connector(MSO_CONNECTOR.STRAIGHT, Inches(x1), Inches(y1),
Inches(x2), Inches(y2))
c.line.color.rgb = color; c.line.width = Pt(w); c.shadow.inherit = False
ln = c.line._get_or_add_ln()
if both:
ln.append(ln.makeelement(qn('a:headEnd'), {'type': 'triangle'}))
ln.append(ln.makeelement(qn('a:tailEnd'), {'type': 'triangle'}))
return c
def group(x, y, w, h, title, tsize=11.5):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=None, line=LIGHT, lw=Pt(1.25), adj=0.04)
txt(x, y + 0.05, w, 0.26, title, size=tsize, color=WHITE, bold=True,
align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.TOP)
def box(x, y, w, h, title, sub=None, fill=WHITE, tcol=INK, tsize=10.5, line=None, lw=Pt(1)):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=fill, line=line, lw=lw, adj=0.16)
tb = s.shapes.add_textbox(Inches(x + 0.05), Inches(y), Inches(w - 0.10), Inches(h))
tf = tb.text_frame; tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.MIDDLE
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER; p.line_spacing = 0.98
r = p.add_run(); r.text = title; r.font.size = Pt(tsize); r.font.bold = True
r.font.name = F; r.font.color.rgb = tcol
if sub is not None:
p.space_after = Pt(2)
p2 = tf.add_paragraph(); p2.alignment = PP_ALIGN.CENTER; p2.line_spacing = 0.98
r2 = p2.add_run(); r2.text = sub; r2.font.size = Pt(tsize - 0.5)
r2.font.name = F; r2.font.color.rgb = SUBC
return tb
AD_Y, AD_H = 3.50, 0.48
def adapter(x, w, title):
box(x, AD_Y, w, AD_H, title, fill=ADC, tcol=INK, tsize=9, line=BLUE, lw=Pt(1.1))
# ---- Hintergrund + Header --------------------------------------------------
shp(MSO_SHAPE.RECTANGLE, 0, 0, SW.inches, SH.inches, fill=BG)
chrome(s, "Event Sourcing — Integrationsserver", 8)
# ---- Legende ---------------------------------------------------------------
ly = 0.95
def legsq(x, color, label, lw_txt):
shp(MSO_SHAPE.RECTANGLE, x, ly + 0.02, 0.15, 0.15, fill=color)
txt(x + 0.21, ly - 0.03, lw_txt, 0.26, label, size=10, color=WHITE, anchor=MSO_ANCHOR.MIDDLE)
legsq(0.40, CORAL, "Event Store", 1.2)
legsq(1.76, GREEN, "Prop-Limbach", 1.3)
legsq(3.28, ADC, "Adapter (own)", 1.4)
legsq(4.90, WHITE, "System", 0.9)
txt(6.30, 0.92, 6.63, 0.3,
"↕ publizieren & abonnieren ↓ publizieren grau = Kommunikation",
size=10, color=LIGHT, italic=True, anchor=MSO_ANCHOR.MIDDLE, align=PP_ALIGN.RIGHT)
# ---- EVENT STORE -----------------------------------------------------------
ST_X, ST_Y, ST_W, ST_H = 0.40, 4.18, 12.53, 0.60
shp(MSO_SHAPE.ROUNDED_RECTANGLE, ST_X, ST_Y, ST_W, ST_H, fill=CORAL, line=INK, lw=Pt(3.5), adj=0.10)
txt(ST_X, ST_Y + 0.06, ST_W, 0.30, "Event Store — append-only Event-Log",
size=15, color=INK, bold=True, align=PP_ALIGN.CENTER)
txt(ST_X, ST_Y + 0.35, ST_W, 0.22, "kanonische Wahrheit · Replay-fähig · (Kafka)",
size=10.5, color=INK, align=PP_ALIGN.CENTER)
# ===========================================================================
# OBEN Systeme + Adapter-Ebene
# ===========================================================================
TGY, TGH = 1.28, 2.78
# --- 1: Order Entry ueber CLAB ---------------------------------------------
group(0.40, TGY, 2.70, TGH, "Order Entry über CLAB")
box(0.52, 1.62, 1.16, 0.42, "LabAccess")
box(1.82, 1.62, 1.16, 0.42, "MDN")
box(1.18, 2.22, 1.14, 0.44, "AB+M")
box(1.05, 2.84, 1.40, 0.42, "CLAB (LIS)", fill=GREEN)
adapter(0.78, 1.94, "CLAB-Adapter")
conn(1.10, 2.04, 1.55, 2.22); conn(2.40, 2.04, 1.95, 2.22)
conn(1.75, 2.66, 1.75, 2.84); conn(1.75, 3.26, 1.75, AD_Y)
conn(1.75, AD_Y + AD_H, 1.75, ST_Y, both=True)
# --- 2: Probeneingang (Atras SL + PVT) -------------------------------------
group(3.26, TGY, 1.95, TGH, "Probeneingang")
box(3.34, 2.30, 0.86, 0.52, "Atras SL")
box(4.27, 2.30, 0.86, 0.52, "PVT")
adapter(3.34, 1.79, "Adapter (Probe → Event)")
conn(2.32, 2.50, 3.34, 2.56, color=GRAY, both=True) # Praeanalytik-Kommunikation
txt(2.28, 2.04, 1.30, 0.34, "Präanalytik-\nKomm.", size=8, color=GRAY, italic=True,
align=PP_ALIGN.CENTER)
conn(3.77, 2.82, 3.95, AD_Y); conn(4.70, 2.82, 4.55, AD_Y)
conn(4.235, AD_Y + AD_H, 4.235, ST_Y)
# --- 3: Geraete -------------------------------------------------------------
group(5.37, TGY, 1.78, TGH, "Geräte-Adapter")
box(5.49, 2.10, 1.54, 0.70, "Geräte", "Sysmex · Analyzer")
adapter(5.45, 1.62, "Adapter (Device → Event)")
conn(6.26, 2.80, 6.26, AD_Y); conn(6.26, AD_Y + AD_H, 6.26, ST_Y, both=True)
# --- 4: Middleware ----------------------------------------------------------
group(7.31, TGY, 1.78, TGH, "Middleware")
box(7.43, 2.10, 1.54, 0.70, "Middleware-Systeme", "Myla/Maestria · LabOps · Liason")
adapter(7.39, 1.62, "Adapter (Middleware → Event)")
conn(8.20, 2.80, 8.20, AD_Y); conn(8.20, AD_Y + AD_H, 8.20, ST_Y, both=True)
# --- 5: MiBi (Hybase) -------------------------------------------------------
group(9.25, TGY, 1.70, TGH, "MiBi")
box(9.37, 2.10, 1.46, 0.70, "Hybase", "Resistenz / ID-Daten")
adapter(9.33, 1.54, "Adapter (MiBi → Event)")
conn(10.10, 2.80, 10.10, AD_Y); conn(10.10, AD_Y + AD_H, 10.10, ST_Y, both=True)
# --- 6: Stammdaten ----------------------------------------------------------
group(11.11, TGY, 1.82, TGH, "Stammdaten")
box(11.23, 2.10, 1.58, 0.70, "Stammdaten-Quellen", "SinaCRM · OTS/Znooni")
adapter(11.19, 1.66, "Adapter (MasterData → Event)")
conn(12.02, 2.80, 12.02, AD_Y); conn(12.02, AD_Y + AD_H, 12.02, ST_Y)
# ===========================================================================
# UNTEN Event-Prozessoren · Projektionen · Konsumenten
# ===========================================================================
BGY, BGH = 4.96, 1.96
group(0.40, BGY, 2.95, BGH, "Event-Prozessoren")
box(0.56, 5.42, 2.63, 0.55, "Mapping / Transformation")
box(0.56, 6.12, 2.63, 0.55, "Routing Engine")
conn(1.85, ST_Y + ST_H, 1.85, BGY, both=True)
group(3.50, BGY, 5.85, BGH, "Projektionen")
box(3.66, 5.46, 1.78, 1.02, "Auftragsstatus")
box(5.56, 5.46, 1.78, 1.02, "Audit Trail")
box(7.46, 5.46, 1.73, 1.02, "Reporting")
conn(6.40, ST_Y + ST_H, 6.40, BGY)
group(9.50, BGY, 3.43, BGH, "Konsumenten")
box(9.66, 5.38, 3.11, 0.68, "SinaBI (Power BI)", "Reporting / BI")
box(9.66, 6.12, 3.11, 0.68, "Archivierung · Vaultbox", "Roche Navify · LDT2")
conn(11.21, ST_Y + ST_H, 11.21, BGY)
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie7.pptx")
prs.save(out)
print("saved", out)
+138
View File
@@ -0,0 +1,138 @@
#!/usr/bin/env python3
"""Folie 8 Funktionszuordnung je System (aus Anforderungskatalog_LIS_Fit-Gap v2.xlsx).
Pro System eine Kachel; Funktionen NUR dort = kraeftig/dunkel, auch woanders = grau mit
'· auch: ...'. Einspaltig, Fira Sans Condensed. (adesso-Stil, deutsch, dunkelblau.)"""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from openpyxl import load_workbook
from openpyxl.utils import column_index_from_string as ci
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, MUTE, RECF,
F, FC, chrome)
BG = RGBColor(0x0A, 0x3D, 0x6B)
SHARE = RGBColor(0x6B, 0x77, 0x85) # grau fuer "auch woanders"
# ---- Daten aus dem Excel lesen --------------------------------------------
HERE = os.path.dirname(os.path.abspath(__file__))
wb = load_workbook(os.path.join(HERE, "Anforderungskatalog_LIS_Fit-Gap v2.xlsx"), data_only=True)
ws = wb["Anforderungen & Fit-Gap"]
SYS = [('H', 'Order Entry'), ('N', 'AB+M'), ('O', 'Integrationsserver'), ('P', 'PVT'),
('Q', 'R. LabOps'), ('R', 'Sysmex'), ('S', 'SAP'), ('T', 'Consens')]
ABBR = {'Order Entry': 'OE', 'AB+M': 'AB+M', 'Integrationsserver': 'Int.-Server',
'PVT': 'PVT', 'R. LabOps': 'R.LabOps', 'Sysmex': 'Sysmex', 'SAP': 'SAP',
'Consens': 'Consens'}
reqs = []; cur = None
for r in range(5, ws.max_row + 1):
b = ws.cell(r, 2).value; c = ws.cell(r, 3).value
marks = {d: (ws.cell(r, ci(col)).value not in (None, '')) for col, d in SYS}
if b:
cur = {'name': (str(c).strip() if c else str(b)), 'm': dict(marks)}
reqs.append(cur)
elif cur:
for d, v in marks.items():
if v: cur['m'][d] = True
if c: cur['name'] = (cur['name'] + ' / ' + str(c).strip())
persys = {d: [] for _, d in SYS}
for req in reqs:
active = [d for _, d in SYS if req['m'][d]]
for d in active:
persys[d].append((req['name'], [o for o in active if o != d]))
for d in persys:
persys[d].sort(key=lambda it: (1 if it[1] else 0))
# ---- PPTX ------------------------------------------------------------------
prs = Presentation(); prs.slide_width = Inches(13.333); prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
s = prs.slides.add_slide(prs.slide_layouts[6])
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), adj=None):
sh = s.shapes.add_shape(kind, Inches(x), Inches(y), Inches(w), Inches(h))
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if adj is not None:
try: sh.adjustments[0] = adj
except Exception: pass
sh.shadow.inherit = False
return sh
def txt(x, y, w, h, t, size=12, color=WHITE, bold=False, align=PP_ALIGN.LEFT,
font=F, anchor=MSO_ANCHOR.MIDDLE):
tb = s.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h)); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = anchor
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
p = tf.paragraphs[0]; p.alignment = align
r = p.add_run(); r.text = t
r.font.size = Pt(size); r.font.bold = bold; r.font.name = font; r.font.color.rgb = color
return tb
def cut(t, n):
return t if len(t) <= n else t[:n].rstrip() + ""
def tile(x, y, w, h, title, items, accent, isize, sa, name_max):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=WHITE, adj=0.05)
txt(x + 0.22, y + 0.14, w - 0.44, 0.32, title, size=14, color=INK, bold=True,
anchor=MSO_ANCHOR.MIDDLE)
n = len([i for i in items if not i[1]])
txt(x + w - 1.7, y + 0.18, 1.5, 0.24, "%d · %d nur hier" % (len(items), n),
size=8.5, color=SHARE, align=PP_ALIGN.RIGHT, font=FC, anchor=MSO_ANCHOR.MIDDLE)
shp(MSO_SHAPE.RECTANGLE, x + 0.22, y + 0.50, w - 0.44, 0.030, fill=accent)
tb = s.shapes.add_textbox(Inches(x + 0.22), Inches(y + 0.62), Inches(w - 0.40),
Inches(h - 0.74))
tf = tb.text_frame; tf.word_wrap = True; tf.vertical_anchor = MSO_ANCHOR.TOP
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
for i, (name, others) in enumerate(items):
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
p.alignment = PP_ALIGN.LEFT; p.line_spacing = 0.96; p.space_after = Pt(sa)
r = p.add_run(); r.font.name = FC; r.font.size = Pt(isize)
if others:
r.text = cut(name, name_max); r.font.bold = False; r.font.color.rgb = SHARE
r2 = p.add_run(); r2.text = " · auch: " + ", ".join(ABBR[o] for o in others)
r2.font.name = FC; r2.font.size = Pt(isize - 1); r2.font.color.rgb = SHARE
else:
r.text = cut(name, name_max + 4); r.font.bold = True; r.font.color.rgb = INK
# ---- Hintergrund + Header --------------------------------------------------
shp(MSO_SHAPE.RECTANGLE, 0, 0, SW.inches, SH.inches, fill=BG)
chrome(s, "Funktionszuordnung je System", 9)
txt(0.42, 0.96, 12.5, 0.3,
"Dunkel/fett = nur dieses System · grau „· auch: …" + chr(34) + " = Funktion liegt auch in anderen Systemen",
size=11, color=LIGHT, anchor=MSO_ANCHOR.MIDDLE, font=FC)
CY, CH = 1.46, 5.42
COLS = [0.40, 3.58, 6.76, 9.94]; CW = 2.98
# Spalte 1: Integrationsserver (hoch)
tile(COLS[0], CY, CW, CH, "Integrationsserver", persys['Integrationsserver'],
CORAL, isize=9, sa=1.5, name_max=30)
# Spalte 2: Order Entry (hoch)
tile(COLS[1], CY, CW, CH, "Order Entry", persys['Order Entry'],
BLUE, isize=10.5, sa=5, name_max=30)
# Spalten 3 & 4: je 3 kleine Kacheln
SH3 = 1.68; GAP = 0.19
ys = [CY, CY + SH3 + GAP, CY + 2 * (SH3 + GAP)]
small3 = ['AB+M', 'Consens', 'R. LabOps']
small4 = ['PVT', 'Sysmex', 'SAP']
for name, y in zip(small3, ys):
tile(COLS[2], y, CW, SH3, name, persys[name], TEAL, isize=9.5, sa=3, name_max=30)
for name, y in zip(small4, ys):
tile(COLS[3], y, CW, SH3, name, persys[name], TEAL, isize=9.5, sa=3, name_max=30)
out = os.path.join(HERE, "Folie8.pptx")
prs.save(out)
print("saved", out)
+122
View File
@@ -0,0 +1,122 @@
#!/usr/bin/env python3
"""Folie 9 Golden Master (adesso-Stil, deutsch, dunkelblau).
Was ist das? · Vorgehen (3 Schritte) · Nutzen 1 + Nutzen 2."""
import os
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE, MSO_CONNECTOR
from pptx.oxml.ns import qn
from adesso_style import (WHITE, INK, BLUE, TEAL, GREEN, CORAL, LIGHT, MUTE, RECF,
F, FC, chrome)
BG = RGBColor(0x0A, 0x3D, 0x6B)
prs = Presentation(); prs.slide_width = Inches(13.333); prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
s = prs.slides.add_slide(prs.slide_layouts[6])
def shp(kind, x, y, w, h, fill=None, line=None, lw=Pt(1), adj=None):
sh = s.shapes.add_shape(kind, Inches(x), Inches(y), Inches(w), Inches(h))
if fill is None: sh.fill.background()
else: sh.fill.solid(); sh.fill.fore_color.rgb = fill
if line is None: sh.line.fill.background()
else: sh.line.color.rgb = line; sh.line.width = lw
if adj is not None:
try: sh.adjustments[0] = adj
except Exception: pass
sh.shadow.inherit = False
return sh
def txt(x, y, w, h, t, size=12, color=WHITE, bold=False, italic=False,
align=PP_ALIGN.LEFT, font=F, anchor=MSO_ANCHOR.MIDDLE):
tb = s.shapes.add_textbox(Inches(x), Inches(y), Inches(w), Inches(h)); tf = tb.text_frame
tf.word_wrap = True; tf.vertical_anchor = anchor
tf.margin_left = tf.margin_right = tf.margin_top = tf.margin_bottom = Pt(0)
first = True
for line in t.split("\n"):
p = tf.paragraphs[0] if first else tf.add_paragraph(); first = False
p.alignment = align
r = p.add_run(); r.text = line
r.font.size = Pt(size); r.font.bold = bold; r.font.italic = italic
r.font.name = font; r.font.color.rgb = color
return tb
def conn(x1, y1, x2, y2, color=LIGHT, w=2.0):
c = s.shapes.add_connector(MSO_CONNECTOR.STRAIGHT, Inches(x1), Inches(y1),
Inches(x2), Inches(y2))
c.line.color.rgb = color; c.line.width = Pt(w); c.shadow.inherit = False
ln = c.line._get_or_add_ln()
ln.append(ln.makeelement(qn('a:tailEnd'), {'type': 'triangle'}))
return c
def heading(x, y, t):
shp(MSO_SHAPE.RECTANGLE, x, y + 0.05, 0.16, 0.20, fill=CORAL)
txt(x + 0.26, y - 0.04, 8.0, 0.34, t, size=15, color=WHITE, bold=True,
anchor=MSO_ANCHOR.MIDDLE)
def step(x, y, w, h, num, title, sub):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=WHITE, adj=0.08)
shp(MSO_SHAPE.OVAL, x + 0.16, y + 0.16, 0.42, 0.42, fill=BLUE)
txt(x + 0.16, y + 0.16, 0.42, 0.42, str(num), size=15, color=WHITE, bold=True,
align=PP_ALIGN.CENTER)
txt(x + 0.70, y + 0.14, w - 0.85, 0.34, title, size=13, color=INK, bold=True,
anchor=MSO_ANCHOR.TOP)
txt(x + 0.70, y + 0.50, w - 0.85, h - 0.60, sub, size=10.5, color=MUTE,
anchor=MSO_ANCHOR.TOP)
def nutzen(x, y, w, h, title, body):
shp(MSO_SHAPE.ROUNDED_RECTANGLE, x, y, w, h, fill=WHITE, adj=0.05)
shp(MSO_SHAPE.RECTANGLE, x, y + 0.16, 0.13, h - 0.32, fill=CORAL)
txt(x + 0.34, y + 0.20, w - 0.55, 0.40, title, size=15, color=INK, bold=True,
anchor=MSO_ANCHOR.TOP)
txt(x + 0.34, y + 0.70, w - 0.6, h - 0.85, body, size=12, color=INK,
anchor=MSO_ANCHOR.TOP)
# ---- Hintergrund + Header --------------------------------------------------
shp(MSO_SHAPE.RECTANGLE, 0, 0, SW.inches, SH.inches, fill=BG)
chrome(s, "Golden Master", 10)
# ---- Was ist das? ----------------------------------------------------------
heading(0.50, 1.22, "Was ist das?")
shp(MSO_SHAPE.ROUNDED_RECTANGLE, 0.50, 1.58, 12.33, 0.82, fill=WHITE, adj=0.06)
txt(0.78, 1.58, 11.8, 0.82,
"Ein umfassender Acceptance-/Approval-Test der Software: Das System wird als Ganzes gegen einen "
"einmal erfassten, freigegebenen Referenz-Stand („Golden Master“) geprüft — weicht ein "
"Ergebnis ab, schlägt der Test an.",
size=12.5, color=INK)
# ---- Vorgehen --------------------------------------------------------------
heading(0.50, 2.64, "Vorgehen")
SY, SH_ = 3.00, 1.06
step(0.50, SY, 3.70, SH_, 1, "Code- & Ergebnis-Analyse",
"Prüfen, wie die Software arbeitet und wie/wo Ergebnisse abgelegt werden.")
step(4.82, SY, 3.70, SH_, 2, "Testtool aufbauen",
"Werkzeug, das Referenz-Ergebnisse erfasst und bei jedem Lauf vergleicht.")
step(9.13, SY, 3.70, SH_, 3, "Test-Suite (Fachseite)",
"Die FS baut die fachlichen Testfälle / Szenarien auf.")
conn(4.24, SY + SH_ / 2, 4.78, SY + SH_ / 2)
conn(8.56, SY + SH_ / 2, 9.09, SY + SH_ / 2)
# ---- Nutzen ----------------------------------------------------------------
heading(0.50, 4.34, "Nutzen")
NY, NH = 4.70, 2.02
nutzen(0.50, NY, 6.00, NH, "Nutzen 1 · Funktionssicherung CLAB",
"Nach jeder Änderung lässt sich die Funktionsfähigkeit der Software prüfen — "
"schnelle, wiederholbare Regressionssicherheit ohne manuelles Nachtesten.")
nutzen(6.83, NY, 6.00, NH, "Nutzen 2 · Vollständigkeit bei LIS-Migration",
"Ein Ziel-LIS, auf das migriert werden soll, lässt sich hart gegen die eigenen "
"Anforderungen testen.\n\n⚠ Setzt ein neues Aufsetzen des Testtools voraus.")
out = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Folie9.pptx")
prs.save(out)
print("saved", out)
+139
View File
@@ -0,0 +1,139 @@
<mxfile host="Electron">
<diagram id="event-sourcing" name="TO-BE (Event Sourcing)">
<mxGraphModel dx="1037" dy="425" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1320" pageHeight="900" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="es_title" parent="1" style="text;html=1;align=left;fontStyle=1;fontSize=16;" value="TO-BE (Variante) — Event-Sourcing-Integration" vertex="1">
<mxGeometry height="26" width="700" x="60" y="10" as="geometry" />
</mxCell>
<mxCell id="es_leg" parent="1" style="text;html=1;align=left;fontStyle=1;" value="Legend" vertex="1">
<mxGeometry height="20" width="60" x="60" y="82" as="geometry" />
</mxCell>
<mxCell id="es_leg_own" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="own" vertex="1">
<mxGeometry height="24" width="80" x="120" y="80" as="geometry" />
</mxCell>
<mxCell id="es_leg_tp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="third-party" vertex="1">
<mxGeometry height="24" width="90" x="210" y="80" as="geometry" />
</mxCell>
<mxCell id="es_leg_ev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF2CC;strokeColor=#D6B656;" value="Event-Store" vertex="1">
<mxGeometry height="24" width="110" x="310" y="80" as="geometry" />
</mxCell>
<mxCell id="es_abm" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="AB+M&#xa;(Order Entry)" vertex="1">
<mxGeometry height="56" width="160" x="130" y="244" as="geometry" />
</mxCell>
<mxCell id="es_lac" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="LabAccess&#xa;(Order Entry I)" vertex="1">
<mxGeometry height="56" width="160" x="60" y="154" as="geometry" />
</mxCell>
<mxCell id="es_mdn" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="MDN&#xa;(Order Entry II)" vertex="1">
<mxGeometry height="56" width="160" x="240" y="154" as="geometry" />
</mxCell>
<mxCell id="es_mds" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="Stammdaten-Quellen&lt;br&gt;SinaCRM · OTS/Znooni / Links" vertex="1">
<mxGeometry height="56" width="230" x="360" y="300" as="geometry" />
</mxCell>
<mxCell id="es_admds" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Adapter&#xa;(MasterData → Event)" vertex="1">
<mxGeometry height="44" width="230" x="360" y="400" as="geometry" />
</mxCell>
<mxCell id="es_store" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF2CC;strokeColor=#D6B656;fontStyle=1;fontSize=13;" value="Event Store — append-only Event-Log&#xa;kanonische Wahrheit · Projektionen abgeleitet · Replay-fähig" vertex="1">
<mxGeometry height="70" width="940" x="70" y="559" as="geometry" />
</mxCell>
<mxCell id="es_pgrp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;verticalAlign=top;fontStyle=1;" value="Event-Prozessoren" vertex="1">
<mxGeometry height="170" width="200" x="980" y="380" as="geometry" />
</mxCell>
<mxCell id="es_pmap" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Mapping / Transformation" vertex="1">
<mxGeometry height="46" width="160" x="1000" y="415" as="geometry" />
</mxCell>
<mxCell id="es_proute" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Routing Engine" vertex="1">
<mxGeometry height="46" width="160" x="1000" y="480" as="geometry" />
</mxCell>
<mxCell id="es_jgrp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#6C8EBF;dashed=1;verticalAlign=top;fontStyle=1;" value="Projektionen / Read-Models" vertex="1">
<mxGeometry height="107" width="470" x="751" y="726" as="geometry" />
</mxCell>
<mxCell id="es_jorder" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;" value="Auftrags-Status" vertex="1">
<mxGeometry height="58" width="130" x="771" y="758" as="geometry" />
</mxCell>
<mxCell id="es_jmd" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;" value="Konsolidierte Stammdaten&#xa;(Single Point of Truth)" vertex="1">
<mxGeometry height="58" width="170" x="916" y="758" as="geometry" />
</mxCell>
<mxCell id="es_jcat" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;" value="Leistungs-&#xa;verzeichnis" vertex="1">
<mxGeometry height="58" width="110" x="1096" y="758" as="geometry" />
</mxCell>
<mxCell id="es_mon" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="Monitoring (Roche Analytics)" vertex="1">
<mxGeometry height="50" width="250" x="603" y="835" as="geometry" />
</mxCell>
<mxCell id="es_adclab" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="CLAB-Adapter" vertex="1">
<mxGeometry height="50" width="160" x="130" y="448" as="geometry" />
</mxCell>
<mxCell id="es_addev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Device- / Middle Ware- Adapter&lt;br&gt;Sysmex IPU · Myla/Maestria · LabOps · Desuri · Liason" vertex="1">
<mxGeometry height="50" width="280" x="283" y="699" as="geometry" />
</mxCell>
<mxCell id="es_clab" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;fontStyle=1;" value="CLAB (LIS)" vertex="1">
<mxGeometry height="56" width="160" x="130" y="356" as="geometry" />
</mxCell>
<mxCell id="es_dev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="Devices&#xa;Sysmex-Straße · Atras SL · Analyzer" vertex="1">
<mxGeometry height="56" width="280" x="290" y="829" as="geometry" />
</mxCell>
<mxCell id="es_e_abm" edge="1" parent="1" source="es_abm" style="endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" target="es_clab">
<mxGeometry relative="1" as="geometry">
<mxPoint x="210" y="344" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="es_e_lac" edge="1" parent="1" source="es_lac" style="endArrow=classic;html=1;rounded=0;entryX=0.306;entryY=-0.018;entryDx=0;entryDy=0;entryPerimeter=0;" target="es_abm">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_e_mdn" edge="1" parent="1" source="es_mdn" style="endArrow=classic;html=1;rounded=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" target="es_abm">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_e_mds" edge="1" parent="1" source="es_mds" style="endArrow=classic;html=1;rounded=0;" target="es_admds">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_p_mds" edge="1" parent="1" source="es_admds" style="endArrow=classic;html=1;rounded=0;fontStyle=2;entryX=0.435;entryY=0.014;entryDx=0;entryDy=0;entryPerimeter=0;" target="es_store" value="publish">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_x_map" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;dashed=1;fontStyle=2;" target="es_pmap" value="consume / publish">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_x_route" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;dashed=1;" target="es_proute">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_order" edge="1" parent="1" source="es_store" style="endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_jorder" value="subscribe">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_md" edge="1" parent="1" source="es_store" style="endArrow=classic;html=1;rounded=0;" target="es_jmd">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_cat" edge="1" parent="1" source="es_store" style="endArrow=classic;html=1;rounded=0;" target="es_jcat">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_mon" edge="1" parent="1" source="es_store" style="edgeStyle=orthogonalEdgeStyle;endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_mon" value="subscribe">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="600" y="737" />
<mxPoint x="720" y="737" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="es_x_clab" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.173;exitY=0.014;exitDx=0;exitDy=0;exitPerimeter=0;" target="es_adclab" value="publish / subscribe">
<mxGeometry relative="1" as="geometry">
<mxPoint x="230" y="541.5384615384614" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="es_x_dev" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" target="es_addev">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_n_clab" edge="1" parent="1" source="es_adclab" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_clab" value="LDT / natives Protokoll">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_n_dev" edge="1" parent="1" source="es_addev" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_dev" value="natives Protokoll">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="hm9u5WX3jjkNatpctnB4-2" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" value="Prop - limbach" vertex="1">
<mxGeometry height="24" width="80" x="440" y="80" as="geometry" />
</mxCell>
<mxCell id="TgiG7C2EhwjrXGmr-nUM-1" parent="1" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;" value="" vertex="1">
<mxGeometry height="40" width="40" x="120" y="574" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+474
View File
@@ -0,0 +1,474 @@
<mxfile host="Electron" pages="4">
<diagram id="as-is" name="AS-IS (heute)">
<mxGraphModel dx="1171" dy="929" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1500" pageHeight="1000" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="title" parent="1" style="text;html=1;align=left;fontStyle=1;fontSize=16;" value="AS-IS — heutige Landschaft (MVZ Ludwigsburg)" vertex="1">
<mxGeometry height="26" width="700" x="60" y="20" as="geometry" />
</mxCell>
<mxCell id="abm" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="AB+M&#xa;Order Entry&#xa;30% Musterschein / 70% digital" vertex="1">
<mxGeometry height="72" width="190" x="80" y="70" as="geometry" />
</mxCell>
<mxCell id="laccess" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="LabAccess&#xa;(Order Entry I)" vertex="1">
<mxGeometry height="72" width="160" x="300" y="70" as="geometry" />
</mxCell>
<mxCell id="mdn" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="MDN&#xa;(Order Entry II)" vertex="1">
<mxGeometry height="72" width="160" x="500" y="70" as="geometry" />
</mxCell>
<mxCell id="bottleneck" parent="1" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#F8CECC;strokeColor=#B85450;fontStyle=2;" value="Nur 1 LDT an CLAB · AB+M muss zuerst abgeschlossen sein → Engpass" vertex="1">
<mxGeometry height="34" width="580" x="80" y="180" as="geometry" />
</mxCell>
<mxCell id="clab" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F5F5F5;strokeColor=#666666;fontStyle=1;fontSize=14;" value="CLAB&#xa;(LIS)" vertex="1">
<mxGeometry height="90" width="240" x="300" y="320" as="geometry" />
</mxCell>
<mxCell id="ipu" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#E1D5E7;strokeColor=#9673A6;" value="Sysmex&#xa;Extended IPU" vertex="1">
<mxGeometry height="60" width="150" x="60" y="520" as="geometry" />
</mxCell>
<mxCell id="myla" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#E1D5E7;strokeColor=#9673A6;" value="Myla → Maestria" vertex="1">
<mxGeometry height="60" width="150" x="230" y="520" as="geometry" />
</mxCell>
<mxCell id="labops" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#E1D5E7;strokeColor=#9673A6;" value="LabOps" vertex="1">
<mxGeometry height="60" width="120" x="400" y="520" as="geometry" />
</mxCell>
<mxCell id="mwrest" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#E1D5E7;strokeColor=#9673A6;" value="Desuri (bidir.) · Biomerieux&#xa;Liason · Firetransfer&#xa;(je eigene P2P-Anbindung)" vertex="1">
<mxGeometry height="60" width="240" x="540" y="520" as="geometry" />
</mxCell>
<mxCell id="devs" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="Geräte: Sysmex-Straße · Atras SL (1)/(2) Schüttgutsortierer · Analyzer" vertex="1">
<mxGeometry height="50" width="720" x="60" y="650" as="geometry" />
</mxCell>
<mxCell id="sdgroup" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#B85450;dashed=1;verticalAlign=top;fontStyle=1;fontColor=#B85450;" value="Stammdaten-Inseln — Doppelpflege" vertex="1">
<mxGeometry height="210" width="380" x="820" y="300" as="geometry" />
</mxCell>
<mxCell id="sd1" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F8CECC;strokeColor=#B85450;" value="CLAB-Stammdaten&#xa;(selbst generiert)" vertex="1">
<mxGeometry height="55" width="160" x="840" y="340" as="geometry" />
</mxCell>
<mxCell id="sd2" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F8CECC;strokeColor=#B85450;" value="SinaCRM&#xa;(separate Pflege z. LIS)" vertex="1">
<mxGeometry height="55" width="160" x="1020" y="340" as="geometry" />
</mxCell>
<mxCell id="sd3" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F8CECC;strokeColor=#B85450;" value="MySQL&#xa;(Support-Requests)" vertex="1">
<mxGeometry height="55" width="160" x="840" y="430" as="geometry" />
</mxCell>
<mxCell id="sd4" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F8CECC;strokeColor=#B85450;" value="OTS / Znooni&#xa;(Leistungsverzeichnis)" vertex="1">
<mxGeometry height="55" width="160" x="1020" y="430" as="geometry" />
</mxCell>
<mxCell id="rgroup" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#82B366;dashed=1;verticalAlign=top;fontStyle=1;fontColor=#82B366;" value="Roche / Analytics" vertex="1">
<mxGeometry height="260" width="380" x="820" y="650" as="geometry" />
</mxCell>
<mxCell id="ccm" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D5E8D4;strokeColor=#82B366;" value="2 × CCM" vertex="1">
<mxGeometry height="50" width="120" x="840" y="690" as="geometry" />
</mxCell>
<mxCell id="navify" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D5E8D4;strokeColor=#82B366;" value="Roche Navify LabOps&#xa;(auch Archivierung)" vertex="1">
<mxGeometry height="50" width="200" x="980" y="690" as="geometry" />
</mxCell>
<mxCell id="ranalytics" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D5E8D4;strokeColor=#82B366;" value="Monitoring von Roche · Analytics (CCM-Daten)&#xa;Roche Integrater · Average of normals" vertex="1">
<mxGeometry height="60" width="340" x="840" y="760" as="geometry" />
</mxCell>
<mxCell id="sinabi" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#D5E8D4;strokeColor=#82B366;" value="SinaBI (PowerBI)" vertex="1">
<mxGeometry height="45" width="160" x="840" y="840" as="geometry" />
</mxCell>
<mxCell id="e1" edge="1" parent="1" source="abm" style="endArrow=classic;html=1;fontStyle=2;" target="clab" value="LDT">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e2" edge="1" parent="1" source="laccess" style="endArrow=classic;html=1;" target="clab">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e3" edge="1" parent="1" source="mdn" style="endArrow=classic;html=1;" target="clab">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e4" edge="1" parent="1" source="ipu" style="endArrow=classic;html=1;" target="clab">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e5" edge="1" parent="1" source="myla" style="endArrow=classic;html=1;" target="clab">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e6" edge="1" parent="1" source="labops" style="endArrow=classic;html=1;" target="clab">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e7" edge="1" parent="1" source="mwrest" style="endArrow=classic;startArrow=classic;html=1;" target="clab">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e8" edge="1" parent="1" source="devs" style="endArrow=classic;html=1;dashed=1;" target="ipu">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e9" edge="1" parent="1" source="devs" style="endArrow=classic;html=1;dashed=1;" target="mwrest">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="r1" edge="1" parent="1" source="clab" style="endArrow=classic;startArrow=classic;html=1;dashed=1;strokeColor=#B85450;fontColor=#B85450;fontStyle=2;" target="sd2" value="separate Pflege">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="r2" edge="1" parent="1" source="clab" style="endArrow=classic;startArrow=classic;html=1;dashed=1;strokeColor=#B85450;" target="sd1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="r3" edge="1" parent="1" source="sd2" style="endArrow=classic;startArrow=classic;html=1;dashed=1;strokeColor=#B85450;fontColor=#B85450;fontStyle=2;" target="sd4" value="manuelles Mapping (Links)">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="r4" edge="1" parent="1" source="sd1" style="endArrow=classic;startArrow=classic;html=1;dashed=1;strokeColor=#B85450;fontColor=#B85450;fontStyle=2;" target="sd3" value="Doppelpflege">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="g1" edge="1" parent="1" source="clab" style="endArrow=classic;startArrow=classic;html=1;" target="navify">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="g2" edge="1" parent="1" source="ccm" style="endArrow=classic;html=1;" target="ranalytics">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="to-be" name="TO-BE (Ziel)">
<mxGraphModel dx="1240" dy="1964" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1000" pageHeight="980" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="t_title" parent="1" style="text;html=1;align=left;fontStyle=1;fontSize=16;" value="TO-BE — Integration Server mit Single Point of Truth" vertex="1">
<mxGeometry height="26" width="700" x="60" y="-30" as="geometry" />
</mxCell>
<mxCell id="leg_t" parent="1" style="text;html=1;align=left;fontStyle=1;" value="Legend" vertex="1">
<mxGeometry height="20" width="70" x="60" y="18" as="geometry" />
</mxCell>
<mxCell id="leg_e" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="own" vertex="1">
<mxGeometry height="24" width="80" x="125" y="16" as="geometry" />
</mxCell>
<mxCell id="leg_f" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="third-party" vertex="1">
<mxGeometry height="24" width="90" x="215" y="16" as="geometry" />
</mxCell>
<mxCell id="gC0" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="LabAccess&#xa;(Order Entry I)" vertex="1">
<mxGeometry height="64" width="170" x="120" y="90" as="geometry" />
</mxCell>
<mxCell id="gB0" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="MDN&#xa;(Order Entry II)" vertex="1">
<mxGeometry height="64" width="170" x="400" y="90" as="geometry" />
</mxCell>
<mxCell id="gA0" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="AB+M&#xa;(Order Entry)" vertex="1">
<mxGeometry height="64" width="170" x="700" y="90" as="geometry" />
</mxCell>
<mxCell id="srv" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F8F8F8;strokeColor=#999999;verticalAlign=top;fontStyle=1;fontSize=14;" value="Integration Server" vertex="1">
<mxGeometry height="420" width="850" x="60" y="250" as="geometry" />
</mxCell>
<mxCell id="absC" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Abstraction" vertex="1">
<mxGeometry height="44" width="170" x="120" y="300" as="geometry" />
</mxCell>
<mxCell id="absB" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Abstraction" vertex="1">
<mxGeometry height="44" width="170" x="400" y="300" as="geometry" />
</mxCell>
<mxCell id="absA" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Order Abstraction" vertex="1">
<mxGeometry height="44" width="170" x="700" y="300" as="geometry" />
</mxCell>
<mxCell id="db" parent="1" style="shape=cylinder3;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;boundedLbl=1;backgroundOutline=1;size=14;verticalAlign=middle;" value="&lt;b&gt;Single Point of Truth&lt;/b&gt;&lt;br&gt;canonical store&lt;br&gt;konsolidiert: Stammdaten · SinaCRM · Leistungsverzeichnis (OTS/Znooni)" vertex="1">
<mxGeometry height="115" width="350" x="320" y="390" as="geometry" />
</mxCell>
<mxCell id="zd" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;verticalAlign=top;fontStyle=1;" value="Central Services" vertex="1">
<mxGeometry height="105" width="560" x="210" y="545" as="geometry" />
</mxCell>
<mxCell id="zd1" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Routing Engine" vertex="1">
<mxGeometry height="50" width="160" x="230" y="580" as="geometry" />
</mxCell>
<mxCell id="zd2" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Mapping / Transformation" vertex="1">
<mxGeometry height="50" width="180" x="405" y="580" as="geometry" />
</mxCell>
<mxCell id="zd3" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Monitoring&#xa;(Roche Analytics)" vertex="1">
<mxGeometry height="50" width="150" x="600" y="580" as="geometry" />
</mxCell>
<mxCell id="lis" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="LIS (CLAB)" vertex="1">
<mxGeometry height="60" width="170" x="120" y="730" as="geometry" />
</mxCell>
<mxCell id="ga" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Device Abstraction&#xa;Sysmex IPU · Myla/Maestria · LabOps · Desuri · Liason" vertex="1">
<mxGeometry height="70" width="210" x="680" y="725" as="geometry" />
</mxCell>
<mxCell id="ger" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="Devices&#xa;Sysmex-Straße · Atras SL · Analyzer" vertex="1">
<mxGeometry height="60" width="210" x="680" y="850" as="geometry" />
</mxCell>
<mxCell id="eC" edge="1" parent="1" source="gC0" style="endArrow=classic;html=1;rounded=0;" target="absC">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="eB" edge="1" parent="1" source="gB0" style="endArrow=classic;html=1;rounded=0;" target="absB">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="eA" edge="1" parent="1" source="gA0" style="endArrow=classic;html=1;rounded=0;" target="absA">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="nC" edge="1" parent="1" source="absC" style="endArrow=classic;html=1;rounded=0;" target="db">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="nB" edge="1" parent="1" source="absB" style="endArrow=classic;html=1;rounded=0;fontStyle=2;" target="db" value="normalize">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="nA" edge="1" parent="1" source="absA" style="endArrow=classic;html=1;rounded=0;" target="db">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="uni" edge="1" parent="1" source="db" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="zd" value="canonical">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="bLis" edge="1" parent="1" source="lis" style="edgeStyle=orthogonalEdgeStyle;endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.15;entryY=1;entryDx=0;entryDy=0;" target="db" value="direct DB access">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="bGa" edge="1" parent="1" source="ga" style="edgeStyle=orthogonalEdgeStyle;endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.85;entryY=1;entryDx=0;entryDy=0;" target="db" value="direct DB access">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="bGaGer" edge="1" parent="1" source="ga" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" target="ger">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="bLisGer" edge="1" parent="1" source="lis" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" target="ger">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="event-sourcing" name="TO-BE (Event Sourcing)">
<mxGraphModel dx="1240" dy="984" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1320" pageHeight="900" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="es_title" parent="1" style="text;html=1;align=left;fontStyle=1;fontSize=16;" value="TO-BE (Variante) — Event-Sourcing-Integration" vertex="1">
<mxGeometry height="26" width="700" x="60" y="10" as="geometry" />
</mxCell>
<mxCell id="es_leg" parent="1" style="text;html=1;align=left;fontStyle=1;" value="Legend" vertex="1">
<mxGeometry height="20" width="60" x="60" y="46" as="geometry" />
</mxCell>
<mxCell id="es_leg_own" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="own" vertex="1">
<mxGeometry height="24" width="80" x="120" y="44" as="geometry" />
</mxCell>
<mxCell id="es_leg_tp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="third-party" vertex="1">
<mxGeometry height="24" width="90" x="210" y="44" as="geometry" />
</mxCell>
<mxCell id="es_leg_ev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF2CC;strokeColor=#D6B656;" value="Event-Store" vertex="1">
<mxGeometry height="24" width="110" x="310" y="44" as="geometry" />
</mxCell>
<mxCell id="es_abm" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="AB+M&#xa;(Order Entry)" vertex="1">
<mxGeometry height="56" width="160" x="70" y="90" as="geometry" />
</mxCell>
<mxCell id="es_lac" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="LabAccess&#xa;(Order Entry I)" vertex="1">
<mxGeometry height="56" width="160" x="260" y="90" as="geometry" />
</mxCell>
<mxCell id="es_mdn" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="MDN&#xa;(Order Entry II)" vertex="1">
<mxGeometry height="56" width="160" x="450" y="90" as="geometry" />
</mxCell>
<mxCell id="es_mds" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="Stammdaten-Quellen&#xa;SinaCRM · OTS/Znooni" vertex="1">
<mxGeometry height="56" width="230" x="650" y="90" as="geometry" />
</mxCell>
<mxCell id="es_adabm" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Adapter&#xa;(Order → Event)" vertex="1">
<mxGeometry height="44" width="160" x="70" y="190" as="geometry" />
</mxCell>
<mxCell id="es_adlac" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Adapter&#xa;(Order → Event)" vertex="1">
<mxGeometry height="44" width="160" x="260" y="190" as="geometry" />
</mxCell>
<mxCell id="es_admdn" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Adapter&#xa;(Order → Event)" vertex="1">
<mxGeometry height="44" width="160" x="450" y="190" as="geometry" />
</mxCell>
<mxCell id="es_admds" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Adapter&#xa;(MasterData → Event)" vertex="1">
<mxGeometry height="44" width="230" x="650" y="190" as="geometry" />
</mxCell>
<mxCell id="es_store" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF2CC;strokeColor=#D6B656;fontStyle=1;fontSize=13;" value="Event Store — append-only Event-Log&#xa;kanonische Wahrheit · Projektionen abgeleitet · Replay-fähig" vertex="1">
<mxGeometry height="70" width="940" x="70" y="290" as="geometry" />
</mxCell>
<mxCell id="es_pgrp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;verticalAlign=top;fontStyle=1;" value="Event-Prozessoren" vertex="1">
<mxGeometry height="170" width="200" x="1050" y="270" as="geometry" />
</mxCell>
<mxCell id="es_pmap" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Mapping / Transformation" vertex="1">
<mxGeometry height="46" width="160" x="1070" y="305" as="geometry" />
</mxCell>
<mxCell id="es_proute" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Routing Engine" vertex="1">
<mxGeometry height="46" width="160" x="1070" y="370" as="geometry" />
</mxCell>
<mxCell id="es_jgrp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#6C8EBF;dashed=1;verticalAlign=top;fontStyle=1;" value="Projektionen / Read-Models" vertex="1">
<mxGeometry height="107" width="470" x="751" y="457" as="geometry" />
</mxCell>
<mxCell id="es_jorder" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;" value="Auftrags-Status" vertex="1">
<mxGeometry height="58" width="130" x="771" y="489" as="geometry" />
</mxCell>
<mxCell id="es_jmd" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;" value="Konsolidierte Stammdaten&#xa;(Single Point of Truth)" vertex="1">
<mxGeometry height="58" width="170" x="916" y="489" as="geometry" />
</mxCell>
<mxCell id="es_jcat" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;" value="Leistungs-&#xa;verzeichnis" vertex="1">
<mxGeometry height="58" width="110" x="1096" y="489" as="geometry" />
</mxCell>
<mxCell id="es_mon" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="Monitoring (Roche Analytics)" vertex="1">
<mxGeometry height="50" width="250" x="603" y="566" as="geometry" />
</mxCell>
<mxCell id="es_adclab" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="CLAB-Adapter" vertex="1">
<mxGeometry height="50" width="160" x="90" y="430" as="geometry" />
</mxCell>
<mxCell id="es_addev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Device-Adapter&#xa;Sysmex IPU · Myla/Maestria · LabOps · Desuri · Liason" vertex="1">
<mxGeometry height="50" width="280" x="290" y="430" as="geometry" />
</mxCell>
<mxCell id="es_clab" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="CLAB (LIS)" vertex="1">
<mxGeometry height="56" width="160" x="90" y="560" as="geometry" />
</mxCell>
<mxCell id="es_dev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="Devices&#xa;Sysmex-Straße · Atras SL · Analyzer" vertex="1">
<mxGeometry height="56" width="280" x="290" y="560" as="geometry" />
</mxCell>
<mxCell id="es_e_abm" edge="1" parent="1" source="es_abm" style="endArrow=classic;html=1;rounded=0;" target="es_adabm">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_e_lac" edge="1" parent="1" source="es_lac" style="endArrow=classic;html=1;rounded=0;" target="es_adlac">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_e_mdn" edge="1" parent="1" source="es_mdn" style="endArrow=classic;html=1;rounded=0;" target="es_admdn">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_e_mds" edge="1" parent="1" source="es_mds" style="endArrow=classic;html=1;rounded=0;" target="es_admds">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_p_abm" edge="1" parent="1" source="es_adabm" style="endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_store" value="publish">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_p_lac" edge="1" parent="1" source="es_adlac" style="endArrow=classic;html=1;rounded=0;" target="es_store">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_p_mdn" edge="1" parent="1" source="es_admdn" style="endArrow=classic;html=1;rounded=0;" target="es_store">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_p_mds" edge="1" parent="1" source="es_admds" style="endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_store" value="publish">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_x_map" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;dashed=1;fontStyle=2;" target="es_pmap" value="consume / publish">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_x_route" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;dashed=1;" target="es_proute">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_order" edge="1" parent="1" source="es_store" style="endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_jorder" value="subscribe">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_md" edge="1" parent="1" source="es_store" style="endArrow=classic;html=1;rounded=0;" target="es_jmd">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_cat" edge="1" parent="1" source="es_store" style="endArrow=classic;html=1;rounded=0;" target="es_jcat">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_mon" edge="1" parent="1" source="es_store" style="edgeStyle=orthogonalEdgeStyle;endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_mon" value="subscribe">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="600" y="468" />
<mxPoint x="720" y="468" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="es_x_clab" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_adclab" value="publish / subscribe">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_x_dev" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" target="es_addev">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_n_clab" edge="1" parent="1" source="es_adclab" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_clab" value="LDT / natives Protokoll">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_n_dev" edge="1" parent="1" source="es_addev" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_dev" value="natives Protokoll">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="event-driven" name="TO-BE (Empfehlung)">
<mxGraphModel dx="1240" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1200" pageHeight="1000" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="m_title" parent="1" style="text;html=1;align=left;fontStyle=1;fontSize=16;" value="TO-BE (Empfehlung) — Canonical Store als System of Record + Integration über Events" vertex="1">
<mxGeometry height="26" width="900" x="60" y="10" as="geometry" />
</mxCell>
<mxCell id="m_leg" parent="1" style="text;html=1;align=left;fontStyle=1;" value="Legend" vertex="1">
<mxGeometry height="20" width="60" x="60" y="46" as="geometry" />
</mxCell>
<mxCell id="m_leg_own" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="own" vertex="1">
<mxGeometry height="24" width="80" x="120" y="44" as="geometry" />
</mxCell>
<mxCell id="m_leg_tp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="third-party" vertex="1">
<mxGeometry height="24" width="90" x="210" y="44" as="geometry" />
</mxCell>
<mxCell id="m_note" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF2CC;strokeColor=#D6B656;dashed=1;fontStyle=2;align=left;spacingLeft=8;" value="Unterschied zu Seite 2: kein direkter DB-Zugriff — Integration ausschließlich über Events.&#xa;Unterschied zu Seite 3: Store ist zustandsbasiertes System of Record, kein append-only Event-Log." vertex="1">
<mxGeometry height="60" width="420" x="700" y="80" as="geometry" />
</mxCell>
<mxCell id="m_lac" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="LabAccess&#xa;(Order Entry I)" vertex="1">
<mxGeometry height="56" width="170" x="80" y="90" as="geometry" />
</mxCell>
<mxCell id="m_mdn" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="MDN&#xa;(Order Entry II)" vertex="1">
<mxGeometry height="56" width="170" x="290" y="90" as="geometry" />
</mxCell>
<mxCell id="m_abm" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="AB+M&#xa;(Order Entry)" vertex="1">
<mxGeometry height="56" width="170" x="500" y="90" as="geometry" />
</mxCell>
<mxCell id="m_adlac" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Adapter" vertex="1">
<mxGeometry height="40" width="170" x="80" y="185" as="geometry" />
</mxCell>
<mxCell id="m_admdn" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Adapter" vertex="1">
<mxGeometry height="40" width="170" x="290" y="185" as="geometry" />
</mxCell>
<mxCell id="m_adabm" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Adapter" vertex="1">
<mxGeometry height="40" width="170" x="500" y="185" as="geometry" />
</mxCell>
<mxCell id="m_srv" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#F8F8F8;strokeColor=#999999;verticalAlign=top;fontStyle=1;fontSize=14;" value="Integration Server" vertex="1">
<mxGeometry height="360" width="1080" x="60" y="270" as="geometry" />
</mxCell>
<mxCell id="m_bus" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;fontStyle=1;fontSize=13;" value="Event Bus — publish / subscribe" vertex="1">
<mxGeometry height="50" width="1020" x="90" y="320" as="geometry" />
</mxCell>
<mxCell id="m_route" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Routing Engine" vertex="1">
<mxGeometry height="50" width="170" x="100" y="430" as="geometry" />
</mxCell>
<mxCell id="m_map" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Mapping / Transformation" vertex="1">
<mxGeometry height="50" width="190" x="300" y="430" as="geometry" />
</mxCell>
<mxCell id="m_mon" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Monitoring&#xa;(Roche Analytics)" vertex="1">
<mxGeometry height="50" width="170" x="520" y="430" as="geometry" />
</mxCell>
<mxCell id="m_store" parent="1" style="shape=cylinder3;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;boundedLbl=1;backgroundOutline=1;size=14;verticalAlign=middle;" value="&lt;b&gt;Single Point of Truth&lt;/b&gt;&lt;br&gt;canonical store · System of Record&lt;br&gt;Stammdaten · SinaCRM · Leistungsverzeichnis (OTS/Znooni)" vertex="1">
<mxGeometry height="150" width="320" x="760" y="410" as="geometry" />
</mxCell>
<mxCell id="m_adclab" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="CLAB-Adapter" vertex="1">
<mxGeometry height="50" width="170" x="120" y="700" as="geometry" />
</mxCell>
<mxCell id="m_addev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Device-Adapter&#xa;Sysmex IPU · Myla/Maestria · LabOps · Desuri · Liason" vertex="1">
<mxGeometry height="50" width="320" x="360" y="700" as="geometry" />
</mxCell>
<mxCell id="m_clab" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="CLAB (LIS)" vertex="1">
<mxGeometry height="56" width="170" x="120" y="800" as="geometry" />
</mxCell>
<mxCell id="m_dev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="Devices&#xa;Sysmex-Straße · Atras SL · Analyzer" vertex="1">
<mxGeometry height="56" width="320" x="360" y="800" as="geometry" />
</mxCell>
<mxCell id="m_e_lac" edge="1" parent="1" source="m_lac" style="endArrow=classic;html=1;rounded=0;" target="m_adlac">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_e_mdn" edge="1" parent="1" source="m_mdn" style="endArrow=classic;html=1;rounded=0;" target="m_admdn">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_e_abm" edge="1" parent="1" source="m_abm" style="endArrow=classic;html=1;rounded=0;" target="m_adabm">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_b_lac" edge="1" parent="1" source="m_adlac" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="m_bus" value="publish / subscribe">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_b_mdn" edge="1" parent="1" source="m_admdn" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" target="m_bus">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_b_abm" edge="1" parent="1" source="m_adabm" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" target="m_bus">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_b_route" edge="1" parent="1" source="m_bus" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="m_route" value="consume / publish">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_b_map" edge="1" parent="1" source="m_bus" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" target="m_map">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_b_mon" edge="1" parent="1" source="m_bus" style="endArrow=classic;html=1;rounded=0;fontStyle=2;" target="m_mon" value="subscribe">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_b_store" edge="1" parent="1" source="m_bus" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="m_store" value="Events → State / Read">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_b_clab" edge="1" parent="1" source="m_bus" style="edgeStyle=orthogonalEdgeStyle;endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;exitX=0.05;exitY=1;exitDx=0;exitDy=0;" target="m_adclab" value="publish / subscribe">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_b_dev" edge="1" parent="1" source="m_bus" style="edgeStyle=orthogonalEdgeStyle;endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;" target="m_addev">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_n_clab" edge="1" parent="1" source="m_adclab" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="m_clab" value="LDT / natives Protokoll">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="m_n_dev" edge="1" parent="1" source="m_addev" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="m_dev" value="natives Protokoll">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
Binary file not shown.
+181
View File
@@ -0,0 +1,181 @@
<mxfile host="Electron">
<diagram id="event-sourcing" name="TO-BE (Event Sourcing)">
<mxGraphModel dx="1240" dy="984" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1320" pageHeight="900" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="rWyWgaAAbOhaxAdMFHOU-9" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" value="" vertex="1">
<mxGeometry height="93" width="500" x="80" y="453" as="geometry" />
</mxCell>
<mxCell id="rWyWgaAAbOhaxAdMFHOU-8" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" value="" vertex="1">
<mxGeometry height="60" width="1110" x="54" y="230" as="geometry" />
</mxCell>
<mxCell id="es_title" parent="1" style="text;html=1;align=left;fontStyle=1;fontSize=16;" value="TO-BE (Variante) — Event-Sourcing-Integration" vertex="1">
<mxGeometry height="26" width="700" x="60" y="10" as="geometry" />
</mxCell>
<mxCell id="es_leg" parent="1" style="text;html=1;align=left;fontStyle=1;" value="Legend" vertex="1">
<mxGeometry height="20" width="60" x="60" y="89" as="geometry" />
</mxCell>
<mxCell id="es_leg_own" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="own" vertex="1">
<mxGeometry height="24" width="80" x="120" y="87" as="geometry" />
</mxCell>
<mxCell id="es_leg_tp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="third-party" vertex="1">
<mxGeometry height="24" width="90" x="210" y="87" as="geometry" />
</mxCell>
<mxCell id="es_leg_ev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF2CC;strokeColor=#D6B656;" value="Event-Store" vertex="1">
<mxGeometry height="24" width="110" x="310" y="87" as="geometry" />
</mxCell>
<mxCell id="es_abm" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="AB+M&#xa;(Order Entry)" vertex="1">
<mxGeometry height="56" width="160" x="70" y="140" as="geometry" />
</mxCell>
<mxCell id="es_lac" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="LabAccess&#xa;(Order Entry I)" vertex="1">
<mxGeometry height="56" width="160" x="260" y="140" as="geometry" />
</mxCell>
<mxCell id="es_mdn" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="MDN&#xa;(Order Entry II)" vertex="1">
<mxGeometry height="56" width="160" x="450" y="140" as="geometry" />
</mxCell>
<mxCell id="es_mds" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="Stammdaten-Quellen&#xa;SinaCRM · OTS/Znooni" vertex="1">
<mxGeometry height="56" width="230" x="650" y="140" as="geometry" />
</mxCell>
<mxCell id="es_adabm" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;strokeWidth=2;" value="Adapter&#xa;(Order → Event)" vertex="1">
<mxGeometry height="44" width="160" x="70" y="240" as="geometry" />
</mxCell>
<mxCell id="es_adlac" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;strokeWidth=2;" value="Adapter&#xa;(Order → Event)" vertex="1">
<mxGeometry height="44" width="160" x="260" y="240" as="geometry" />
</mxCell>
<mxCell id="es_admdn" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;strokeWidth=2;" value="Adapter&#xa;(Order → Event)" vertex="1">
<mxGeometry height="44" width="160" x="450" y="240" as="geometry" />
</mxCell>
<mxCell id="es_admds" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;strokeWidth=2;" value="Adapter&#xa;(MasterData → Event)" vertex="1">
<mxGeometry height="44" width="230" x="650" y="240" as="geometry" />
</mxCell>
<mxCell id="es_store" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFF2CC;strokeColor=#D6B656;fontStyle=1;fontSize=13;" value="Event Store — append-only Event-Log&#xa;kanonische Wahrheit · Projektionen abgeleitet · Replay-fähig" vertex="1">
<mxGeometry height="70" width="940" x="70" y="340" as="geometry" />
</mxCell>
<mxCell id="es_pgrp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;verticalAlign=top;fontStyle=1;" value="Event-Prozessoren" vertex="1">
<mxGeometry height="170" width="200" x="1050" y="320" as="geometry" />
</mxCell>
<mxCell id="es_pmap" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Mapping / Transformation" vertex="1">
<mxGeometry height="46" width="160" x="1070" y="355" as="geometry" />
</mxCell>
<mxCell id="es_proute" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Routing Engine" vertex="1">
<mxGeometry height="46" width="160" x="1070" y="420" as="geometry" />
</mxCell>
<mxCell id="es_jgrp" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;dashed=1;verticalAlign=top;fontStyle=1;" value="Projektionen / Read-Models" vertex="1">
<mxGeometry height="107" width="470" x="751" y="507" as="geometry" />
</mxCell>
<mxCell id="es_jorder" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;" value="Auftrags-Status" vertex="1">
<mxGeometry height="58" width="130" x="771" y="539" as="geometry" />
</mxCell>
<mxCell id="es_jmd" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;" value="Konsolidierte Stammdaten&#xa;(Single Point of Truth)" vertex="1">
<mxGeometry height="58" width="170" x="916" y="539" as="geometry" />
</mxCell>
<mxCell id="es_jcat" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#EAF0FB;strokeColor=#6C8EBF;" value="Leistungs-&#xa;verzeichnis" vertex="1">
<mxGeometry height="58" width="110" x="1096" y="539" as="geometry" />
</mxCell>
<mxCell id="es_mon" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;" value="Monitoring (Roche Analytics)" vertex="1">
<mxGeometry height="50" width="250" x="603" y="633" as="geometry" />
</mxCell>
<mxCell id="es_adclab" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="CLAB-Adapter" vertex="1">
<mxGeometry height="50" width="160" x="90" y="480" as="geometry" />
</mxCell>
<mxCell id="es_addev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;" value="Device-Adapter&#xa;Sysmex IPU · Myla/Maestria · LabOps · Desuri · Liason" vertex="1">
<mxGeometry height="50" width="280" x="290" y="480" as="geometry" />
</mxCell>
<mxCell id="es_clab" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="CLAB (LIS)" vertex="1">
<mxGeometry height="56" width="160" x="90" y="627" as="geometry" />
</mxCell>
<mxCell id="es_dev" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="Devices&#xa;Sysmex-Straße · Atras SL · Analyzer" vertex="1">
<mxGeometry height="56" width="280" x="290" y="627" as="geometry" />
</mxCell>
<mxCell id="es_e_abm" edge="1" parent="1" source="es_abm" style="endArrow=classic;html=1;rounded=0;" target="es_adabm">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_e_lac" edge="1" parent="1" source="es_lac" style="endArrow=classic;html=1;rounded=0;" target="es_adlac">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_e_mdn" edge="1" parent="1" source="es_mdn" style="endArrow=classic;html=1;rounded=0;" target="es_admdn">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_e_mds" edge="1" parent="1" source="es_mds" style="endArrow=classic;html=1;rounded=0;" target="es_admds">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_p_abm" edge="1" parent="1" source="es_adabm" style="endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_store" value="publish">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_p_lac" edge="1" parent="1" source="es_adlac" style="endArrow=classic;html=1;rounded=0;" target="es_store">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_p_mdn" edge="1" parent="1" source="es_admdn" style="endArrow=classic;html=1;rounded=0;" target="es_store">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_p_mds" edge="1" parent="1" source="es_admds" style="endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_store" value="publish">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_x_map" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;dashed=1;fontStyle=2;" target="es_pmap" value="consume / publish">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_x_route" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;dashed=1;" target="es_proute">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_order" edge="1" parent="1" source="es_store" style="endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_jorder" value="subscribe">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_md" edge="1" parent="1" source="es_store" style="endArrow=classic;html=1;rounded=0;" target="es_jmd">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_cat" edge="1" parent="1" source="es_store" style="endArrow=classic;html=1;rounded=0;" target="es_jcat">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_s_mon" edge="1" parent="1" source="es_store" style="edgeStyle=orthogonalEdgeStyle;endArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_mon" value="subscribe">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="600" y="518" />
<mxPoint x="720" y="518" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="es_x_clab" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_adclab" value="publish / subscribe">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_x_dev" edge="1" parent="1" source="es_store" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" target="es_addev">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_n_clab" edge="1" parent="1" source="es_adclab" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_clab" value="LDT / natives Protokoll">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="es_n_dev" edge="1" parent="1" source="es_addev" style="endArrow=classic;startArrow=classic;html=1;rounded=0;fontStyle=2;" target="es_dev" value="natives Protokoll">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="rWyWgaAAbOhaxAdMFHOU-1" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#FFE6CC;strokeColor=#D79B00;fontStyle=1;" value="weitere thrd. Pratry Apps&lt;div&gt;...&lt;/div&gt;" vertex="1">
<mxGeometry height="60" width="230" x="916" y="140" as="geometry" />
</mxCell>
<mxCell id="rWyWgaAAbOhaxAdMFHOU-2" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#DAE8FC;strokeColor=#6C8EBF;strokeWidth=2;" value="app - adapter" vertex="1">
<mxGeometry height="44" width="230" x="916" y="240" as="geometry" />
</mxCell>
<mxCell id="rWyWgaAAbOhaxAdMFHOU-3" edge="1" parent="1" source="rWyWgaAAbOhaxAdMFHOU-2" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;">
<mxGeometry relative="1" as="geometry">
<mxPoint x="790" y="340" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="rWyWgaAAbOhaxAdMFHOU-4" connectable="0" parent="rWyWgaAAbOhaxAdMFHOU-3" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" value="publish" vertex="1">
<mxGeometry relative="1" x="-0.2089" y="2" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="rWyWgaAAbOhaxAdMFHOU-5" edge="1" parent="1" source="rWyWgaAAbOhaxAdMFHOU-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" target="rWyWgaAAbOhaxAdMFHOU-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="rWyWgaAAbOhaxAdMFHOU-10" parent="1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;" value="Abstraktion" vertex="1">
<mxGeometry height="24" width="110" x="437" y="87" as="geometry" />
</mxCell>
<mxCell id="rWyWgaAAbOhaxAdMFHOU-11" parent="1" style="shape=cylinder3;whiteSpace=wrap;html=1;boundedLbl=1;backgroundOutline=1;size=15;fillColor=#fff2cc;strokeColor=#000000;strokeWidth=2;" value="" vertex="1">
<mxGeometry height="50" width="60" x="101" y="351" as="geometry" />
</mxCell>
<mxCell id="rWyWgaAAbOhaxAdMFHOU-13" parent="1" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;rounded=0;" value="master- data" vertex="1">
<mxGeometry height="30" width="70" x="170" y="340" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+20
View File
@@ -0,0 +1,20 @@
#!/usr/bin/env python3
"""Fügt Folie2, Folie3, Folie4 zu einer Datei zusammen (Reihenfolge 2, 3, 4)."""
import copy
import os
from pptx import Presentation
base = os.path.dirname(os.path.abspath(__file__)) + "/"
dst = Presentation(base + "Folie2.pptx") # Seite 1 = Folie 2
blank = dst.slide_layouts[6]
for fname in ("Folie3.pptx", "Folie3b.pptx", "Folie4.pptx"): # Seiten 2, 3, 4, 5
src = Presentation(base + fname)
new_slide = dst.slides.add_slide(blank)
for shape in src.slides[0].shapes:
new_slide.shapes._spTree.append(copy.deepcopy(shape._element))
out = base + "Workshop_LIS.pptx"
dst.save(out)
print("saved", out)