initial
This commit is contained in:
@@ -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)
|
||||
Reference in New Issue
Block a user