This commit is contained in:
marcus.hinz
2026-06-20 09:14:17 +02:00
parent f63f8c2f1c
commit e6175308e0
23 changed files with 1343 additions and 1 deletions
Vendored
BIN
View File
Binary file not shown.
@@ -0,0 +1,138 @@
<mxfile host="Electron" agent="Claude">
<diagram id="blazor-arch" name="Blazor Architecture - Two Faces">
<mxGraphModel dx="2074" dy="850" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1280" pageHeight="1000" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="fe_box" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=6;fillColor=light-dark(#c0e3ff, #1d293b);strokeColor=#6c8ebf;fontStyle=1;fontSize=14;verticalAlign=bottom;spacingTop=8;align=left;spacingLeft=12;spacingBottom=10;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=4;" value="Blazor Frontend (DE / EN) — Client" vertex="1">
<mxGeometry height="150" width="1120" x="40" y="106" as="geometry" />
</mxCell>
<mxCell id="face1" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=10;fillColor=light-dark(#e6fec3, #1f2f1e);strokeColor=light-dark(#76c800, #446e2c);fontSize=13;align=center;verticalAlign=middle;fontStyle=1;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Strang 1 — Ressourcen und Contentverwaltung&lt;br&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Excel Import/Export, Rules, IPAS (SAP)&lt;br&gt;Klassen, Attribute, Tabellen, Autorules&lt;/span&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="85" width="430" x="80" y="131" as="geometry" />
</mxCell>
<mxCell id="be_box" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=6;fillColor=light-dark(#e5fec1, #1f2f1e);strokeColor=light-dark(#76c800, #446e2c);fontStyle=1;fontSize=14;verticalAlign=bottom;spacingTop=8;align=left;spacingLeft=12;spacingBottom=10;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=4;" value=".NET 8 Backend (Web API)" vertex="1">
<mxGeometry height="290" width="540" x="50" y="367" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-21" edge="1" parent="1" source="svc_import" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#97D077;strokeWidth=2;" target="svc_class">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="svc_import" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ccff83, #1f2f1e);strokeColor=#82b366;fontSize=12;align=center;fontStyle=1;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;Import Service&lt;br&gt;Daten Normalisierung&lt;br&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Excel / XML&lt;/span&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="58" width="151" x="59" y="416" as="geometry" />
</mxCell>
<mxCell id="svc_class" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ccff83, #ededed);strokeColor=#82b366;fontSize=12;align=center;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;&lt;b&gt;Klassifizierung&lt;br&gt;&lt;/b&gt;Klassen, Attribute&lt;/font&gt;" vertex="1">
<mxGeometry height="58" width="150" x="235" y="416" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-22" edge="1" parent="1" source="svc_rules" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#97D077;" target="cad_exec">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="svc_rules" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ccff83, #1f2f1e);strokeColor=#82b366;fontSize=12;align=center;html=1;fontStyle=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;Rule Engine&lt;br&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Autorules DSL&lt;/span&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="58" width="150" x="250" y="499" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-23" edge="1" parent="1" source="cad_exec" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;strokeWidth=2;strokeColor=#97D077;startArrow=classic;startFill=1;" target="svc_class">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cad_exec" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ccff83, #1f2f1e);strokeColor=#82b366;fontSize=12;align=center;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;&lt;b&gt;Autorules Executor&lt;/b&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="58" width="140" x="410" y="416" as="geometry" />
</mxCell>
<mxCell id="be_cross" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=#f5f5f5;strokeColor=#999999;fontSize=11;align=center;fontStyle=2;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Logging · Auth · Localization · JSON API" vertex="1">
<mxGeometry height="40" width="230" x="340" y="596" as="geometry" />
</mxCell>
<mxCell id="db" parent="1" style="shape=cylinder3;whiteSpace=wrap;boundedLbl=1;backgroundOutline=1;size=8;fillColor=light-dark(#fde0f1, #392f3f);strokeColor=light-dark(#f566ba, #9577a3);fontSize=12;align=center;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=4;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;&lt;b&gt;Datenbank (SQL Server / PostgreSQL)&lt;/b&gt;&lt;br&gt;Klassen, Objekte, Attribute, Regeltabellen, Tabellen&lt;/font&gt;" vertex="1">
<mxGeometry height="95" width="360" x="92" y="702" as="geometry" />
</mxCell>
<mxCell id="queue" parent="1" style="rounded=1;whiteSpace=wrap;shape=process;fillColor=light-dark(#fff2cc, #3a3320);strokeColor=#d6b656;fontSize=14;fontStyle=1;align=center;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="Queue" vertex="1">
<mxGeometry height="55" width="260" x="765" y="277" as="geometry" />
</mxCell>
<mxCell id="cad_svc" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=6;fillColor=light-dark(#ffeae0, #281d00);strokeColor=light-dark(#ff9868, #6d5100);fontStyle=1;fontSize=14;verticalAlign=bottom;spacingTop=8;align=left;spacingLeft=12;spacingBottom=10;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=4;" value="CAD Service" vertex="1">
<mxGeometry height="250" width="460" x="655" y="371" as="geometry" />
</mxCell>
<mxCell id="cad_plugin" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ffeae0, #281d00);strokeColor=light-dark(#ff9868, #6d5100);fontSize=12;align=left;html=1;verticalAlign=bottom;spacingLeft=6;fontStyle=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;spacingBottom=5;" value="Creo - Service PlugIn" vertex="1">
<mxGeometry height="132" width="400" x="685" y="387" as="geometry" />
</mxCell>
<mxCell id="cad_access" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ffeae0, #ededed);strokeColor=light-dark(#ff9868, #6d5100);fontSize=12;align=center;html=1;fontStyle=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Access Layer" vertex="1">
<mxGeometry height="28" width="360" x="705" y="404" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-2" edge="1" parent="1" source="cad_jlink" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;strokeColor=#E3A065;startArrow=classic;startFill=1;" target="cad_creo">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cad_jlink" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ffeae0, #281d00);strokeColor=light-dark(#ff9868, #6d5100);fontSize=12;align=center;html=1;fontStyle=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Java Bridge → Creo (J-Link)" vertex="1">
<mxGeometry height="45" width="360" x="705" y="444" as="geometry" />
</mxCell>
<mxCell id="cad_creo" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ffeae0, #281d00);strokeColor=light-dark(#ff9868, #6d5100);fontSize=13;align=center;html=1;fontStyle=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="PTC CREO" vertex="1">
<mxGeometry height="60" width="200" x="785" y="545" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-19" edge="1" parent="1" source="ext_wc" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" target="cad_creo">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ext_wc" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=#f5f5f5;strokeColor=#999999;fontSize=12;fontStyle=1;align=center;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="Windchill&#xa;(PDM)" vertex="1">
<mxGeometry height="60" width="120" x="1140" y="545" as="geometry" />
</mxCell>
<mxCell id="leg1" parent="1" style="text;fontSize=12;fontColor=light-dark(#76c800, #446e2c);fontStyle=1;align=left;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="■ Grün = CRUD / .NET Backend" vertex="1">
<mxGeometry height="20" width="240" x="50" y="891" as="geometry" />
</mxCell>
<mxCell id="leg2" parent="1" style="text;fontSize=12;fontColor=light-dark(#ff9868, #6d5100);fontStyle=1;align=left;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="■ Orange = CAD Service" vertex="1">
<mxGeometry height="20" width="145" x="231" y="891" as="geometry" />
</mxCell>
<mxCell id="leg3" parent="1" style="text;fontSize=12;fontColor=#d6b656;fontStyle=1;align=left;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="■ Gelb = Queue" vertex="1">
<mxGeometry height="20" width="100" x="380" y="891" as="geometry" />
</mxCell>
<mxCell id="e_rest" edge="1" parent="1" source="fe_box" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;strokeColor=light-dark(#76c800, #446e2c);strokeWidth=3;startArrow=classic;startFill=1;endArrow=classic;endFill=1;fontSize=12;fontStyle=2;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" target="be_box" value="REST / SignalR">
<mxGeometry relative="1" y="20" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="e_efcore" edge="1" parent="1" source="be_box" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;strokeColor=light-dark(#f566ba, #9577a3);strokeWidth=3;fontSize=11;fontStyle=2;exitX=0.411;exitY=1.003;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;exitPerimeter=0;" target="db" value="EF Core">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-1" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=10;fillColor=light-dark(#e6fec3, #1f2f1e);strokeColor=light-dark(#76c800, #446e2c);fontSize=13;align=center;verticalAlign=middle;fontStyle=1;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Strang 2 — CAD Steuerung&lt;br&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;Auftrags- und Ergebnissverarbeitung&lt;/span&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="85" width="430" x="680" y="131" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-5" edge="1" parent="1" source="-et3D9VFUusq47QecnUc-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;strokeWidth=2;strokeColor=#E3A065;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" target="queue">
<mxGeometry relative="1" as="geometry">
<mxPoint x="890" y="295" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-9" edge="1" parent="1" source="queue" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.522;entryY=0.012;entryDx=0;entryDy=0;entryPerimeter=0;fontColor=#E3A065;strokeColor=#E3A065;strokeWidth=2;startArrow=classic;startFill=1;" target="cad_svc">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-11" edge="1" parent="1" source="cad_exec" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;strokeWidth=2;curved=1;endArrow=none;endFill=0;startArrow=classic;startFill=1;fillColor=#d5e8d4;strokeColor=light-dark(#76c800, #446e2c);dashed=1;dashPattern=8 8;" target="-et3D9VFUusq47QecnUc-1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="370" y="521" as="sourcePoint" />
<mxPoint x="628" y="169" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-12" connectable="0" parent="-et3D9VFUusq47QecnUc-11" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=12;" value="&lt;font face=&quot;Fira Sans&quot; data-font-src=&quot;https://fonts.googleapis.com/css?family=Fira+Sans&quot;&gt;Read&lt;/font&gt;" vertex="1">
<mxGeometry relative="1" x="-0.3289" y="-4" as="geometry">
<mxPoint x="41" y="-49" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-13" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=6;fillColor=#f5f5f5;strokeColor=#999999;fontStyle=1;fontSize=14;verticalAlign=bottom;spacingTop=8;align=left;dashed=1;dashPattern=8 4;spacingLeft=10;spacingBottom=10;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="Weitere Konsumenten" vertex="1">
<mxGeometry height="150" width="270" x="655" y="706" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-14" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=#f5f5f5;strokeColor=#999999;fontSize=12;fontStyle=1;align=left;spacingLeft=5;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Sizing Tool" vertex="1">
<mxGeometry height="40" width="135" x="684" y="719" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-15" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=#f5f5f5;strokeColor=#999999;fontSize=12;fontStyle=1;align=left;spacingLeft=5;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Montage- Berechnung" vertex="1">
<mxGeometry height="40" width="135" x="684" y="776" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-16" edge="1" parent="1" source="-et3D9VFUusq47QecnUc-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.655;entryDx=0;entryDy=0;curved=1;dashed=1;dashPattern=8 8;strokeWidth=2;entryPerimeter=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" target="cad_exec">
<mxGeometry relative="1" as="geometry">
<mxPoint x="745" y="580" as="sourcePoint" />
<mxPoint x="610" y="417" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-17" connectable="0" parent="-et3D9VFUusq47QecnUc-16" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=12;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="Read" vertex="1">
<mxGeometry relative="1" x="-0.3236" y="-4" as="geometry">
<mxPoint x="28" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-18" parent="1" style="shape=note;size=20;whiteSpace=wrap;html=1;fontSize=10;align=left;labelPosition=center;verticalLabelPosition=middle;verticalAlign=middle;spacingLeft=10;fontStyle=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Schnittstelle offen&lt;br&gt;Annahme:&lt;br&gt;XML- Export im legacy Format&amp;nbsp;" vertex="1">
<mxGeometry height="40" width="162" x="469" y="778" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-20" parent="1" style="shape=note;size=20;whiteSpace=wrap;html=1;fontSize=10;align=left;labelPosition=center;verticalLabelPosition=middle;verticalAlign=middle;spacingLeft=10;fontStyle=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="&lt;font style=&quot;font-size: 11px;&quot;&gt;Verknüpftes&amp;nbsp;&lt;/font&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px;&quot;&gt;PDM&lt;/font&gt;&lt;/div&gt;" vertex="1">
<mxGeometry height="37" width="95" x="1085" y="504" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
@@ -0,0 +1,138 @@
<mxfile host="Electron" agent="Claude">
<diagram id="blazor-arch" name="Blazor Architecture - Two Faces">
<mxGraphModel dx="2074" dy="850" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1280" pageHeight="1000" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="fe_box" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=6;fillColor=light-dark(#c0e3ff, #1d293b);strokeColor=#6c8ebf;fontStyle=1;fontSize=14;verticalAlign=bottom;spacingTop=8;align=left;spacingLeft=12;spacingBottom=10;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=4;" value="Blazor Frontend (DE / EN) — Client" vertex="1">
<mxGeometry height="150" width="1120" x="40" y="30" as="geometry" />
</mxCell>
<mxCell id="face1" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=10;fillColor=light-dark(#e6fec3, #1f2f1e);strokeColor=light-dark(#76c800, #446e2c);fontSize=13;align=center;verticalAlign=middle;fontStyle=1;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Strang 1 — Ressourcen und Contentverwaltung&lt;br&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Excel Import/Export, Rules, IPAS (SAP)&lt;br&gt;Klassen, Attribute, Tabellen, Autorules&lt;/span&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="85" width="430" x="80" y="55" as="geometry" />
</mxCell>
<mxCell id="be_box" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=6;fillColor=light-dark(#e5fec1, #1f2f1e);strokeColor=light-dark(#76c800, #446e2c);fontStyle=1;fontSize=14;verticalAlign=bottom;spacingTop=8;align=left;spacingLeft=12;spacingBottom=10;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=4;" value=".NET 8 Backend (Web API)" vertex="1">
<mxGeometry height="290" width="540" x="50" y="291" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-21" edge="1" parent="1" source="svc_import" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeColor=#97D077;strokeWidth=2;" target="svc_class">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="svc_import" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ccff83, #1f2f1e);strokeColor=#82b366;fontSize=12;align=center;fontStyle=1;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;Import Service&lt;br&gt;Daten Normalisierung&lt;br&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Excel / XML&lt;/span&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="58" width="151" x="59" y="340" as="geometry" />
</mxCell>
<mxCell id="svc_class" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ccff83, #ededed);strokeColor=#82b366;fontSize=12;align=center;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;&lt;b&gt;Klassifizierung&lt;br&gt;&lt;/b&gt;Klassen, Attribute&lt;/font&gt;" vertex="1">
<mxGeometry height="58" width="150" x="235" y="340" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-22" edge="1" parent="1" source="svc_rules" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeWidth=2;strokeColor=#97D077;" target="cad_exec">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="svc_rules" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ccff83, #1f2f1e);strokeColor=#82b366;fontSize=12;align=center;html=1;fontStyle=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;Rule Engine&lt;br&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;Autorules DSL&lt;/span&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="58" width="150" x="250" y="423" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-23" edge="1" parent="1" source="cad_exec" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;endArrow=none;endFill=0;strokeWidth=2;strokeColor=#97D077;startArrow=classic;startFill=1;" target="svc_class">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cad_exec" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ccff83, #1f2f1e);strokeColor=#82b366;fontSize=12;align=center;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;&lt;b&gt;Autorules Executor&lt;/b&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="58" width="140" x="410" y="340" as="geometry" />
</mxCell>
<mxCell id="be_cross" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=#f5f5f5;strokeColor=#999999;fontSize=11;align=center;fontStyle=2;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Logging · Auth · Localization · JSON API" vertex="1">
<mxGeometry height="40" width="230" x="340" y="520" as="geometry" />
</mxCell>
<mxCell id="db" parent="1" style="shape=cylinder3;whiteSpace=wrap;boundedLbl=1;backgroundOutline=1;size=8;fillColor=light-dark(#fde0f1, #392f3f);strokeColor=light-dark(#f566ba, #9577a3);fontSize=12;align=center;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=4;" value="&lt;font style=&quot;font-size: 13px;&quot;&gt;&lt;b&gt;Datenbank (SQL Server / PostgreSQL)&lt;/b&gt;&lt;br&gt;Klassen, Objekte, Attribute, Regeltabellen, Tabellen&lt;/font&gt;" vertex="1">
<mxGeometry height="95" width="360" x="92" y="626" as="geometry" />
</mxCell>
<mxCell id="queue" parent="1" style="rounded=1;whiteSpace=wrap;shape=process;fillColor=light-dark(#fff2cc, #3a3320);strokeColor=#d6b656;fontSize=14;fontStyle=1;align=center;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="Queue" vertex="1">
<mxGeometry height="55" width="260" x="765" y="201" as="geometry" />
</mxCell>
<mxCell id="cad_svc" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=6;fillColor=light-dark(#ffeae0, #281d00);strokeColor=light-dark(#ff9868, #6d5100);fontStyle=1;fontSize=14;verticalAlign=bottom;spacingTop=8;align=left;spacingLeft=12;spacingBottom=10;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=4;" value="CAD Service" vertex="1">
<mxGeometry height="250" width="460" x="655" y="295" as="geometry" />
</mxCell>
<mxCell id="cad_plugin" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ffeae0, #281d00);strokeColor=light-dark(#ff9868, #6d5100);fontSize=12;align=left;html=1;verticalAlign=bottom;spacingLeft=6;fontStyle=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;spacingBottom=5;" value="Creo - Service PlugIn" vertex="1">
<mxGeometry height="132" width="400" x="685" y="311" as="geometry" />
</mxCell>
<mxCell id="cad_access" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ffeae0, #ededed);strokeColor=light-dark(#ff9868, #6d5100);fontSize=12;align=center;html=1;fontStyle=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Access Layer" vertex="1">
<mxGeometry height="28" width="360" x="705" y="328" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-2" edge="1" parent="1" source="cad_jlink" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;strokeColor=#E3A065;startArrow=classic;startFill=1;" target="cad_creo">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="cad_jlink" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ffeae0, #281d00);strokeColor=light-dark(#ff9868, #6d5100);fontSize=12;align=center;html=1;fontStyle=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Java Bridge → Creo (J-Link)" vertex="1">
<mxGeometry height="45" width="360" x="705" y="368" as="geometry" />
</mxCell>
<mxCell id="cad_creo" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=light-dark(#ffeae0, #281d00);strokeColor=light-dark(#ff9868, #6d5100);fontSize=13;align=center;html=1;fontStyle=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="PTC CREO" vertex="1">
<mxGeometry height="60" width="200" x="785" y="469" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-19" edge="1" parent="1" source="ext_wc" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" target="cad_creo">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ext_wc" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=#f5f5f5;strokeColor=#999999;fontSize=12;fontStyle=1;align=center;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="Windchill&#xa;(PDM)" vertex="1">
<mxGeometry height="60" width="120" x="1140" y="469" as="geometry" />
</mxCell>
<mxCell id="leg1" parent="1" style="text;fontSize=12;fontColor=light-dark(#76c800, #446e2c);fontStyle=1;align=left;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="■ Grün = CRUD / .NET Backend" vertex="1">
<mxGeometry height="20" width="240" x="50" y="891" as="geometry" />
</mxCell>
<mxCell id="leg2" parent="1" style="text;fontSize=12;fontColor=light-dark(#ff9868, #6d5100);fontStyle=1;align=left;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="■ Orange = CAD Service" vertex="1">
<mxGeometry height="20" width="145" x="231" y="891" as="geometry" />
</mxCell>
<mxCell id="leg3" parent="1" style="text;fontSize=12;fontColor=#d6b656;fontStyle=1;align=left;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="■ Gelb = Queue" vertex="1">
<mxGeometry height="20" width="100" x="380" y="891" as="geometry" />
</mxCell>
<mxCell id="e_rest" edge="1" parent="1" source="fe_box" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;strokeColor=light-dark(#76c800, #446e2c);strokeWidth=3;startArrow=classic;startFill=1;endArrow=classic;endFill=1;fontSize=12;fontStyle=2;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" target="be_box" value="REST / SignalR">
<mxGeometry relative="1" y="20" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="e_efcore" edge="1" parent="1" source="be_box" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;strokeColor=light-dark(#f566ba, #9577a3);strokeWidth=3;fontSize=11;fontStyle=2;exitX=0.411;exitY=1.003;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;exitPerimeter=0;" target="db" value="EF Core">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-1" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=10;fillColor=light-dark(#e6fec3, #1f2f1e);strokeColor=light-dark(#76c800, #446e2c);fontSize=13;align=center;verticalAlign=middle;fontStyle=1;html=1;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Strang 2 — CAD Steuerung&lt;br&gt;&lt;span style=&quot;font-weight: 400;&quot;&gt;Auftrags- und Ergebnissverarbeitung&lt;/span&gt;&lt;/font&gt;" vertex="1">
<mxGeometry height="85" width="430" x="680" y="55" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-5" edge="1" parent="1" source="-et3D9VFUusq47QecnUc-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;strokeWidth=2;strokeColor=#E3A065;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" target="queue">
<mxGeometry relative="1" as="geometry">
<mxPoint x="890" y="219" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-9" edge="1" parent="1" source="queue" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.522;entryY=0.012;entryDx=0;entryDy=0;entryPerimeter=0;fontColor=#E3A065;strokeColor=#E3A065;strokeWidth=2;startArrow=classic;startFill=1;" target="cad_svc">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-11" edge="1" parent="1" source="cad_exec" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;strokeWidth=2;curved=1;endArrow=none;endFill=0;startArrow=classic;startFill=1;fillColor=#d5e8d4;strokeColor=light-dark(#76c800, #446e2c);dashed=1;dashPattern=8 8;" target="-et3D9VFUusq47QecnUc-1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="370" y="445" as="sourcePoint" />
<mxPoint x="628" y="93" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-12" connectable="0" parent="-et3D9VFUusq47QecnUc-11" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=12;" value="&lt;font face=&quot;Fira Sans&quot; data-font-src=&quot;https://fonts.googleapis.com/css?family=Fira+Sans&quot;&gt;Read&lt;/font&gt;" vertex="1">
<mxGeometry relative="1" x="-0.3289" y="-4" as="geometry">
<mxPoint x="41" y="-49" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-13" parent="1" style="rounded=1;whiteSpace=wrap;arcSize=6;fillColor=#f5f5f5;strokeColor=#999999;fontStyle=1;fontSize=14;verticalAlign=bottom;spacingTop=8;align=left;dashed=1;dashPattern=8 4;spacingLeft=10;spacingBottom=10;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=3;" value="Weitere Konsumenten" vertex="1">
<mxGeometry height="150" width="270" x="655" y="630" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-14" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=#f5f5f5;strokeColor=#999999;fontSize=12;fontStyle=1;align=left;spacingLeft=5;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Sizing Tool" vertex="1">
<mxGeometry height="40" width="135" x="684" y="643" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-15" parent="1" style="rounded=1;whiteSpace=wrap;fillColor=#f5f5f5;strokeColor=#999999;fontSize=12;fontStyle=1;align=left;spacingLeft=5;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Montage- Berechnung" vertex="1">
<mxGeometry height="40" width="135" x="684" y="700" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-16" edge="1" parent="1" source="-et3D9VFUusq47QecnUc-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.655;entryDx=0;entryDy=0;curved=1;dashed=1;dashPattern=8 8;strokeWidth=2;entryPerimeter=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" target="cad_exec">
<mxGeometry relative="1" as="geometry">
<mxPoint x="745" y="504" as="sourcePoint" />
<mxPoint x="610" y="341" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-17" connectable="0" parent="-et3D9VFUusq47QecnUc-16" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];fontSize=12;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;" value="Read" vertex="1">
<mxGeometry relative="1" x="-0.3236" y="-4" as="geometry">
<mxPoint x="28" as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-18" parent="1" style="shape=note;size=20;whiteSpace=wrap;html=1;fontSize=10;align=left;labelPosition=center;verticalLabelPosition=middle;verticalAlign=middle;spacingLeft=10;fontStyle=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="Schnittstelle offen&lt;br&gt;Annahme:&lt;br&gt;XML- Export im legacy Format&amp;nbsp;" vertex="1">
<mxGeometry height="40" width="162" x="469" y="702" as="geometry" />
</mxCell>
<mxCell id="-et3D9VFUusq47QecnUc-20" parent="1" style="shape=note;size=20;whiteSpace=wrap;html=1;fontSize=10;align=left;labelPosition=center;verticalLabelPosition=middle;verticalAlign=middle;spacingLeft=10;fontStyle=0;fontFamily=Fira Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DFira%2BSans;strokeWidth=2;" value="&lt;font style=&quot;font-size: 11px;&quot;&gt;Verknüpftes&amp;nbsp;&lt;/font&gt;&lt;div&gt;&lt;font style=&quot;font-size: 11px;&quot;&gt;PDM&lt;/font&gt;&lt;/div&gt;" vertex="1">
<mxGeometry height="37" width="95" x="1085" y="428" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
BIN
View File
Binary file not shown.
+2 -1
View File
@@ -5,7 +5,8 @@
"mcp__outline__update_document",
"mcp__outline__create_document",
"mcp__outline__list_documents",
"mcp__outline__move_document"
"mcp__outline__move_document",
"Bash(python3 *)"
]
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+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)
+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>
Binary file not shown.
+1
View File
@@ -1,3 +1,4 @@
- [Limbach Workshop / Outline](limbach-workshop-outline.md) — Wissensaufbau in Outline für Workshop 15./16.06.2026
- [adesso Styling](adesso-styling.md) — Corporate-Template-Quelle & Design-Tokens für Folien 24 (adesso_style.py)
- [Verbotene Wörter](verbotene-woerter.md) — „Pointe", „der Hit", „der Clou" & reißerische Wörter nie verwenden
- [Integrationsserver Aufwand](integrationsserver-aufwand.md) — grobe Aufwandsschätzung Event-Sourcing-Integrationsserver (~300530 PT)
@@ -0,0 +1,34 @@
---
name: integrationsserver-aufwand
description: "Grobe Aufwandsschätzung für den Event-Sourcing-Integrationsserver (Limbach, Stand 2026-06-18)"
metadata:
node_type: memory
type: project
originSessionId: 3a4207d2-1bbd-40f0-9637-4230d2a92919
---
Grobe Order-of-Magnitude-Schätzung (KEIN Angebot) für das Aufsetzen eines **Event-Sourcing-Integrationsservers** (Kafka + Kafka Streams → PostgreSQL) mit den Systemen aus [[limbach-workshop-outline]] / Folie 7 (Order Entry über CLAB, Probeneingang [Atras SL + PVT], Geräte, Middleware, MiBi/Hybase, Stammdaten; Konsumenten SinaBI/Power BI, Archivierung/Vaultbox).
**Gesamt grob: ~300530 PT (≈ 1527 Personenmonate; mit Team 46 ≈ 58 Monate Laufzeit).**
Bausteine (PT):
- Plattform-Foundation (Kafka, Schema Registry, Infra, CI/CD, Monitoring): 2545
- Core (Mapping/Transformation, Routing Engine, Projektions-Framework): 2550
- Adapter CLAB (LDT, bidirektional, zentraler Order-Pfad): 2540
- Adapter Probeneingang (Atras SL + PVT): 1530
- Adapter Geräte (Sysmex/Analyzer, HL7/ASTM, bidirektional): 2035
- Adapter Middleware (Myla/Maestria, LabOps, Liason): 2545
- Adapter MiBi/Hybase: 1525
- Adapter Stammdaten (SinaCRM, OTS/Znooni) + MDM/Dedup: 2035
- Projektionen/Read-Models (Auftragsstatus, Audit Trail, Reporting): 1530
- Konsumenten (SinaBI/Power BI, Archivierung/Vaultbox): 1225
- Golden-Master-Testharness: 1020
- Security/Auth/Compliance (Audit-Trail, DSGVO, Rollen, RiliBÄK-Doku): 1530
- + Architektur/PM/Test-Mgmt/Doku/Rollout (~2530 %)
**MVP-Schnitt** (Plattform + CLAB + Geräte + 1 Projektion + Golden Master): ~100160 PT (~34 Monate).
Größte Kostentreiber/Risiken: Verfügbarkeit & Qualität der Schnittstellen je System (LDT/HL7/ASTM/native, API vorhanden?); Bidirektionalität (Order-Rückweg); Stammdaten-Dedup; Parallelbetrieb/Migration/Replay; Regulatorik (RiliBÄK, ISO 15189, IfSG, DSGVO); Abhängigkeit von Limbach-/Drittanbieter-Ressourcen (CLAB-LDT, Vaultbox/LDT2).
**Why:** Im Workshop kam die Frage nach dem ungefähren Aufwand; die Zahlen sind die abgestimmte grobe Hausnummer.
**How to apply:** Als Ausgangspunkt für Aufwands-/Roadmap-Diskussionen nutzen; bei Bedarf in PT, Personenmonaten oder (mit Tagessatz) als €-Spanne darstellen. Vor jeder Nutzung an konkreten Schnittstellen-Infos je System schärfen. Nutzer wollte daraus ausdrücklich KEINE Folie.