bom layer: add service and controller for BOM and variant nodes

This commit is contained in:
2026-08-26 23:15:09 +02:00
parent adc4179747
commit b2ce536723
4 changed files with 568 additions and 4 deletions
+184
View File
@@ -0,0 +1,184 @@
<mxfile host="Electron">
<diagram name="Seite-1" id="myvTh0tq4TJzTD2Yx8FL">
<mxGraphModel dx="910" dy="1660" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="gn_KE6UjUNWKz2jZffen-1" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" value="BOM" vertex="1">
<mxGeometry height="150" width="180" x="39" y="-420" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-2" parent="gn_KE6UjUNWKz2jZffen-1" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="180" y="30" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-3" parent="gn_KE6UjUNWKz2jZffen-2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-4" parent="gn_KE6UjUNWKz2jZffen-2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" value="id" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-5" parent="gn_KE6UjUNWKz2jZffen-1" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="60" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-6" parent="gn_KE6UjUNWKz2jZffen-5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-7" parent="gn_KE6UjUNWKz2jZffen-5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="productId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-8" parent="gn_KE6UjUNWKz2jZffen-1" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="90" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-9" parent="gn_KE6UjUNWKz2jZffen-8" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-10" parent="gn_KE6UjUNWKz2jZffen-8" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="label" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-11" parent="gn_KE6UjUNWKz2jZffen-1" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="120" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-12" parent="gn_KE6UjUNWKz2jZffen-11" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-13" parent="gn_KE6UjUNWKz2jZffen-11" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="description&amp;nbsp; / parentBOMId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-20" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" value="BOMContent" vertex="1">
<mxGeometry height="150" width="180" x="340" y="-420" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-21" parent="gn_KE6UjUNWKz2jZffen-20" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="180" y="30" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-22" parent="gn_KE6UjUNWKz2jZffen-21" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-23" parent="gn_KE6UjUNWKz2jZffen-21" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" value="id" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-24" parent="gn_KE6UjUNWKz2jZffen-20" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="60" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-25" parent="gn_KE6UjUNWKz2jZffen-24" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-26" parent="gn_KE6UjUNWKz2jZffen-24" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="BOMId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-27" parent="gn_KE6UjUNWKz2jZffen-20" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="90" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-28" parent="gn_KE6UjUNWKz2jZffen-27" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-29" parent="gn_KE6UjUNWKz2jZffen-27" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="productId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-30" parent="gn_KE6UjUNWKz2jZffen-20" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="120" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-31" parent="gn_KE6UjUNWKz2jZffen-30" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-32" parent="gn_KE6UjUNWKz2jZffen-30" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="min / max / mandatory" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-35" edge="1" parent="1" source="gn_KE6UjUNWKz2jZffen-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" target="gn_KE6UjUNWKz2jZffen-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-36" edge="1" parent="1" source="gn_KE6UjUNWKz2jZffen-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="gn_KE6UjUNWKz2jZffen-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-37" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" value="VariantFolder" vertex="1">
<mxGeometry height="150" width="180" x="39" y="-190" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-38" parent="gn_KE6UjUNWKz2jZffen-37" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="180" y="30" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-39" parent="gn_KE6UjUNWKz2jZffen-38" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-40" parent="gn_KE6UjUNWKz2jZffen-38" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" value="id" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-41" parent="gn_KE6UjUNWKz2jZffen-37" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="60" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-42" parent="gn_KE6UjUNWKz2jZffen-41" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-43" parent="gn_KE6UjUNWKz2jZffen-41" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="label" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-44" parent="gn_KE6UjUNWKz2jZffen-37" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="90" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-45" parent="gn_KE6UjUNWKz2jZffen-44" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-46" parent="gn_KE6UjUNWKz2jZffen-44" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="description" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-47" parent="gn_KE6UjUNWKz2jZffen-37" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="120" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-48" parent="gn_KE6UjUNWKz2jZffen-47" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-49" parent="gn_KE6UjUNWKz2jZffen-47" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="BOMId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-50" edge="1" parent="1" source="gn_KE6UjUNWKz2jZffen-47" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="gn_KE6UjUNWKz2jZffen-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+247
View File
@@ -0,0 +1,247 @@
<mxfile host="Electron">
<diagram name="Seite-1" id="myvTh0tq4TJzTD2Yx8FL">
<mxGraphModel dx="910" dy="1660" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="gn_KE6UjUNWKz2jZffen-1" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" value="BOM" vertex="1">
<mxGeometry height="150" width="180" x="39" y="-420" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-2" parent="gn_KE6UjUNWKz2jZffen-1" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="180" y="30" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-3" parent="gn_KE6UjUNWKz2jZffen-2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-4" parent="gn_KE6UjUNWKz2jZffen-2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" value="id" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-5" parent="gn_KE6UjUNWKz2jZffen-1" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="60" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-6" parent="gn_KE6UjUNWKz2jZffen-5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-7" parent="gn_KE6UjUNWKz2jZffen-5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="productId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-8" parent="gn_KE6UjUNWKz2jZffen-1" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="90" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-9" parent="gn_KE6UjUNWKz2jZffen-8" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-10" parent="gn_KE6UjUNWKz2jZffen-8" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="label" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-11" parent="gn_KE6UjUNWKz2jZffen-1" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="120" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-12" parent="gn_KE6UjUNWKz2jZffen-11" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-13" parent="gn_KE6UjUNWKz2jZffen-11" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="description&amp;nbsp; / parentBOMId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-20" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" value="BOMContent" vertex="1">
<mxGeometry height="150" width="180" x="340" y="-420" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-21" parent="gn_KE6UjUNWKz2jZffen-20" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="180" y="30" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-22" parent="gn_KE6UjUNWKz2jZffen-21" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-23" parent="gn_KE6UjUNWKz2jZffen-21" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" value="id" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-24" parent="gn_KE6UjUNWKz2jZffen-20" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="60" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-25" parent="gn_KE6UjUNWKz2jZffen-24" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-26" parent="gn_KE6UjUNWKz2jZffen-24" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="BOMId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-27" parent="gn_KE6UjUNWKz2jZffen-20" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="90" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-28" parent="gn_KE6UjUNWKz2jZffen-27" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-29" parent="gn_KE6UjUNWKz2jZffen-27" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="productId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-30" parent="gn_KE6UjUNWKz2jZffen-20" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="120" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-31" parent="gn_KE6UjUNWKz2jZffen-30" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-32" parent="gn_KE6UjUNWKz2jZffen-30" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="min / max / mandatory" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-35" edge="1" parent="1" source="gn_KE6UjUNWKz2jZffen-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" target="gn_KE6UjUNWKz2jZffen-24">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="280" y="-375" />
<mxPoint x="280" y="-345" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-36" edge="1" parent="1" source="gn_KE6UjUNWKz2jZffen-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="gn_KE6UjUNWKz2jZffen-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-37" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" value="VariantFolder" vertex="1">
<mxGeometry height="150" width="180" x="39" y="-190" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-38" parent="gn_KE6UjUNWKz2jZffen-37" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="180" y="30" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-39" parent="gn_KE6UjUNWKz2jZffen-38" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-40" parent="gn_KE6UjUNWKz2jZffen-38" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" value="id" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-41" parent="gn_KE6UjUNWKz2jZffen-37" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="60" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-42" parent="gn_KE6UjUNWKz2jZffen-41" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-43" parent="gn_KE6UjUNWKz2jZffen-41" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="label" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-44" parent="gn_KE6UjUNWKz2jZffen-37" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="90" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-45" parent="gn_KE6UjUNWKz2jZffen-44" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-46" parent="gn_KE6UjUNWKz2jZffen-44" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="description" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-47" parent="gn_KE6UjUNWKz2jZffen-37" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="120" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-48" parent="gn_KE6UjUNWKz2jZffen-47" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-49" parent="gn_KE6UjUNWKz2jZffen-47" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="BOMId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-50" edge="1" parent="1" source="gn_KE6UjUNWKz2jZffen-47" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="gn_KE6UjUNWKz2jZffen-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-51" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" value="VariantContent" vertex="1">
<mxGeometry height="150" width="180" x="340" y="-190" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-52" parent="gn_KE6UjUNWKz2jZffen-51" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="180" y="30" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-53" parent="gn_KE6UjUNWKz2jZffen-52" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-54" parent="gn_KE6UjUNWKz2jZffen-52" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" value="ID" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-55" parent="gn_KE6UjUNWKz2jZffen-51" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="60" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-56" parent="gn_KE6UjUNWKz2jZffen-55" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-57" parent="gn_KE6UjUNWKz2jZffen-55" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="VariantFolderId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-58" parent="gn_KE6UjUNWKz2jZffen-51" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="90" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-59" parent="gn_KE6UjUNWKz2jZffen-58" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-60" parent="gn_KE6UjUNWKz2jZffen-58" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="productId" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-61" parent="gn_KE6UjUNWKz2jZffen-51" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="180" y="120" as="geometry" />
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-62" parent="gn_KE6UjUNWKz2jZffen-61" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-63" parent="gn_KE6UjUNWKz2jZffen-61" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" value="Row 3" vertex="1">
<mxGeometry height="30" width="150" x="30" as="geometry">
<mxRectangle height="30" width="150" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="gn_KE6UjUNWKz2jZffen-64" edge="1" parent="1" source="gn_KE6UjUNWKz2jZffen-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="gn_KE6UjUNWKz2jZffen-55">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
+4 -4
View File
@@ -11,10 +11,10 @@ import (
)
type BOMController struct {
bomService *services.BOMService
bomService *services.BomService
}
func NewBOMController(b *services.BOMService) *BOMController {
func NewBOMController(b *services.BomService) *BOMController {
return &BOMController{
bomService: b,
}
@@ -72,7 +72,7 @@ func (bc *BOMController) CreateVariantNode(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
err = bc.bomService.CreateVariantNode(&variantNode)
_, err = bc.bomService.CreateVariantNode(&variantNode)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
@@ -117,7 +117,7 @@ func (bc *BOMController) GetVariantNode(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
variantNode, err := bc.bomService.GetVariantNodeById(variantNodeId)
variantNode, err := bc.bomService.GetVariantNode(variantNodeId)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
+133
View File
@@ -0,0 +1,133 @@
package services
import (
"fmt"
"simplycpq/models"
"simplycpq/repositories"
)
type BomService struct {
bomRepository *repositories.BomRepository
}
func NewBomService(bomRepo *repositories.BomRepository) *BomService {
return &BomService{
bomRepository: bomRepo,
}
}
func (bs *BomService) GetBOMByProductID(productID int) ([]models.BillOfMaterial, error) {
bomData, err := bs.bomRepository.GetBOMByProductID(productID)
if err != nil {
return nil, fmt.Errorf("failed to retrieve BOM data: %w", err)
}
return bomData, nil
}
func (bs *BomService) CreateBillOfMaterial(bom *models.BillOfMaterial) error {
// Validate the BOM data
if bom.ProductID <= 0 {
return fmt.Errorf("invalid product ID")
}
// Create the BOM in the repository
err := bs.bomRepository.CreateBillOfMaterial(bom)
if err != nil {
return fmt.Errorf("failed to create BOM: %w", err)
}
return nil
}
func (bs *BomService) GetBOMProductsByBOMId(bomId int64) ([]models.Product, error) {
products, err := bs.bomRepository.GetBOMProductsByBOMId(bomId)
if err != nil {
return nil, fmt.Errorf("failed to retrieve BOM products: %w", err)
}
return products, nil
}
func (bs *BomService) GetBOMVariantNodesByBOMId(bomId int64) ([]models.VariantNode, error) {
variantNodes, err := bs.bomRepository.GetBOMVariantNodesByBOMId(bomId)
if err != nil {
return nil, fmt.Errorf("failed to retrieve BOM variant nodes: %w", err)
}
return variantNodes, nil
}
func (bs *BomService) CreateVariantNode(variantNode *models.VariantNode) (*models.VariantNode, error) {
// Create the VariantNode in the repository
variantNode, err := bs.bomRepository.CreateVariantNode(variantNode)
if err != nil {
return nil, fmt.Errorf("failed to create VariantNode: %w", err)
}
return variantNode, nil
}
func (bs *BomService) GetVariantNodeByID(id int64) (*models.VariantNode, error) {
variantNode, err := bs.bomRepository.GetVariantNodeByID(id)
if err != nil {
return nil, fmt.Errorf("failed to retrieve VariantNode: %w", err)
}
return variantNode, nil
}
func (bs *BomService) UpdateVariantNode(variantNode *models.VariantNode) error {
// Update the VariantNode in the repository
err := bs.bomRepository.UpdateVariantNode(variantNode)
if err != nil {
return fmt.Errorf("failed to update VariantNode: %w", err)
}
return nil
}
func (bs *BomService) DeleteVariantNode(id int64) error {
// Delete the VariantNode in the repository
err := bs.bomRepository.DeleteVariantNode(id)
if err != nil {
return fmt.Errorf("failed to delete VariantNode: %w", err)
}
return nil
}
func (bs *BomService) GetVariantNode(parentID int64) ([]models.VariantNode, error) {
variantNodes, err := bs.bomRepository.GetVariantNode(parentID)
if err != nil {
return nil, fmt.Errorf("failed to retrieve VariantNodes: %w", err)
}
return variantNodes, nil
}
func (bs *BomService) GetVariantNodeProductsByVariantNodeId(parentID int64) ([]models.Product, error) {
products, err := bs.bomRepository.GetVariantNodeProductsByVariantNodeId(parentID)
if err != nil {
return nil, fmt.Errorf("failed to retrieve VariantNode products: %w", err)
}
return products, nil
}
func (bs *BomService) UpdateBillOfMaterial(bom *models.BillOfMaterial) error {
// Update the BOM in the repository
err := bs.bomRepository.UpdateBillOfMaterial(bom)
if err != nil {
return fmt.Errorf("failed to update BOM: %w", err)
}
return nil
}
func (bs *BomService) DeleteBillOfMaterial(id int64) error {
// Delete the BOM in the repository
err := bs.bomRepository.DeleteBillOfMaterial(id)
if err != nil {
return fmt.Errorf("failed to delete BOM: %w", err)
}
return nil
}
func (bs *BomService) GetBillOfMaterial(id int64) (*models.BillOfMaterial, error) {
bom, err := bs.bomRepository.GetBillOfMaterial(id)
if err != nil {
return nil, fmt.Errorf("failed to retrieve BOM: %w", err)
}
return bom, nil
}