717 lines
23 KiB
PHP
717 lines
23 KiB
PHP
<?php
|
|
/* Copyright (C) 2026 Alles Watt lauft
|
|
*
|
|
* PDF Export for Schematic Editor (Leitungslaufplan)
|
|
* Following DIN EN 61082 (Document structure) and DIN EN 81346 (Reference designation)
|
|
*/
|
|
|
|
$res = 0;
|
|
if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php";
|
|
if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php";
|
|
if (!$res && file_exists("../../../../main.inc.php")) $res = @include "../../../../main.inc.php";
|
|
if (!$res) die("Include of main fails");
|
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
|
|
dol_include_once('/kundenkarte/class/anlage.class.php');
|
|
dol_include_once('/kundenkarte/class/equipment.class.php');
|
|
dol_include_once('/kundenkarte/class/equipmentcarrier.class.php');
|
|
dol_include_once('/kundenkarte/class/equipmentconnection.class.php');
|
|
|
|
$langs->loadLangs(array('companies', 'kundenkarte@kundenkarte'));
|
|
|
|
// Get parameters
|
|
$anlageId = GETPOSTINT('anlage_id');
|
|
$svgContent = GETPOST('svg_content', 'restricthtml');
|
|
$format = GETPOST('format', 'alpha') ?: 'A4';
|
|
$orientation = GETPOST('orientation', 'alpha') ?: 'L'; // L=Landscape, P=Portrait
|
|
|
|
// Security check
|
|
if (!$user->hasRight('kundenkarte', 'read')) {
|
|
accessforbidden();
|
|
}
|
|
|
|
// Load Anlage data
|
|
$anlage = new Anlage($db);
|
|
if ($anlage->fetch($anlageId) <= 0) {
|
|
die('Anlage not found');
|
|
}
|
|
|
|
// Load company
|
|
$societe = new Societe($db);
|
|
$societe->fetch($anlage->fk_soc);
|
|
|
|
// Load carriers for this anlage
|
|
$carrier = new EquipmentCarrier($db);
|
|
$carriers = $carrier->fetchByAnlage($anlageId);
|
|
|
|
// Load equipment
|
|
$equipment = new Equipment($db);
|
|
$equipmentList = array();
|
|
foreach ($carriers as $c) {
|
|
$eqList = $equipment->fetchByCarrier($c->id);
|
|
$equipmentList = array_merge($equipmentList, $eqList);
|
|
}
|
|
|
|
// Load connections
|
|
$connection = new EquipmentConnection($db);
|
|
$connections = array();
|
|
foreach ($carriers as $c) {
|
|
$connList = $connection->fetchByCarrier($c->id);
|
|
$connections = array_merge($connections, $connList);
|
|
}
|
|
|
|
// Create PDF - Landscape A3 or A4 for schematic
|
|
$pdf = pdf_getInstance();
|
|
$pdf->SetCreator('Dolibarr - Kundenkarte Schaltplan');
|
|
$pdf->SetAuthor($user->getFullName($langs));
|
|
$pdf->SetTitle('Leitungslaufplan - '.$anlage->label);
|
|
|
|
// Page format
|
|
if ($format == 'A3') {
|
|
$pageWidth = 420;
|
|
$pageHeight = 297;
|
|
} else {
|
|
$pageWidth = 297;
|
|
$pageHeight = 210;
|
|
}
|
|
|
|
if ($orientation == 'P') {
|
|
$tmp = $pageWidth;
|
|
$pageWidth = $pageHeight;
|
|
$pageHeight = $tmp;
|
|
}
|
|
|
|
$pdf->SetMargins(10, 10, 10);
|
|
$pdf->SetAutoPageBreak(false);
|
|
$pdf->AddPage($orientation, array($pageWidth, $pageHeight));
|
|
|
|
// ============================================
|
|
// DIN EN 61082 / ISO 7200 Title Block (Schriftfeld)
|
|
// Position: Bottom right corner
|
|
// ============================================
|
|
|
|
$titleBlockWidth = 180;
|
|
$titleBlockHeight = 56;
|
|
$titleBlockX = $pageWidth - $titleBlockWidth - 10;
|
|
$titleBlockY = $pageHeight - $titleBlockHeight - 10;
|
|
|
|
// Draw title block frame
|
|
$pdf->SetDrawColor(0, 0, 0);
|
|
$pdf->SetLineWidth(0.5);
|
|
$pdf->Rect($titleBlockX, $titleBlockY, $titleBlockWidth, $titleBlockHeight);
|
|
|
|
// Title block grid - following DIN structure
|
|
// Row heights from bottom: 8, 8, 8, 8, 8, 8, 8 = 56mm total
|
|
$rowHeight = 8;
|
|
$rows = 7;
|
|
|
|
// Column widths: 30 | 50 | 50 | 50 = 180mm
|
|
$col1 = 30; // Labels
|
|
$col2 = 50; // Company info
|
|
$col3 = 50; // Document info
|
|
$col4 = 50; // Revision info
|
|
|
|
// Draw horizontal lines
|
|
for ($i = 1; $i < $rows; $i++) {
|
|
$y = $titleBlockY + ($i * $rowHeight);
|
|
$pdf->Line($titleBlockX, $y, $titleBlockX + $titleBlockWidth, $y);
|
|
}
|
|
|
|
// Draw vertical lines
|
|
$pdf->Line($titleBlockX + $col1, $titleBlockY, $titleBlockX + $col1, $titleBlockY + $titleBlockHeight);
|
|
$pdf->Line($titleBlockX + $col1 + $col2, $titleBlockY, $titleBlockX + $col1 + $col2, $titleBlockY + $titleBlockHeight);
|
|
$pdf->Line($titleBlockX + $col1 + $col2 + $col3, $titleBlockY, $titleBlockX + $col1 + $col2 + $col3, $titleBlockY + $titleBlockHeight);
|
|
|
|
// Fill in title block content
|
|
$pdf->SetFont('dejavusans', '', 6);
|
|
$pdf->SetTextColor(0, 0, 0);
|
|
|
|
// Row 1 (from top): Document title spanning full width
|
|
$pdf->SetFont('dejavusans', 'B', 12);
|
|
$pdf->SetXY($titleBlockX + 2, $titleBlockY + 1);
|
|
$pdf->Cell($titleBlockWidth - 4, $rowHeight - 2, 'LEITUNGSLAUFPLAN', 0, 0, 'C');
|
|
|
|
// Row 2: Installation name
|
|
$pdf->SetFont('dejavusans', 'B', 10);
|
|
$pdf->SetXY($titleBlockX + 2, $titleBlockY + $rowHeight + 1);
|
|
$pdf->Cell($titleBlockWidth - 4, $rowHeight - 2, $anlage->label, 0, 0, 'C');
|
|
|
|
// Row 3: Labels
|
|
$pdf->SetFont('dejavusans', '', 6);
|
|
$y = $titleBlockY + (2 * $rowHeight);
|
|
$pdf->SetXY($titleBlockX + 1, $y + 1);
|
|
$pdf->Cell($col1 - 2, 3, 'Erstellt', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + 1, $y + 1);
|
|
$pdf->Cell($col2 - 2, 3, 'Kunde', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + 1, $y + 1);
|
|
$pdf->Cell($col3 - 2, 3, 'Projekt-Nr.', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + $col3 + 1, $y + 1);
|
|
$pdf->Cell($col4 - 2, 3, 'Blatt', 0, 0, 'L');
|
|
|
|
// Row 3: Values
|
|
$pdf->SetFont('dejavusans', '', 8);
|
|
$pdf->SetXY($titleBlockX + 1, $y + 4);
|
|
$pdf->Cell($col1 - 2, 4, dol_print_date(dol_now(), 'day'), 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + 1, $y + 4);
|
|
$pdf->Cell($col2 - 2, 4, dol_trunc($societe->name, 25), 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + 1, $y + 4);
|
|
$pdf->Cell($col3 - 2, 4, $anlage->ref ?: '-', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + $col3 + 1, $y + 4);
|
|
$pdf->Cell($col4 - 2, 4, '1 / 1', 0, 0, 'L');
|
|
|
|
// Row 4: More labels
|
|
$y = $titleBlockY + (3 * $rowHeight);
|
|
$pdf->SetFont('dejavusans', '', 6);
|
|
$pdf->SetXY($titleBlockX + 1, $y + 1);
|
|
$pdf->Cell($col1 - 2, 3, 'Bearbeiter', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + 1, $y + 1);
|
|
$pdf->Cell($col2 - 2, 3, 'Adresse', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + 1, $y + 1);
|
|
$pdf->Cell($col3 - 2, 3, 'Anlage', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + $col3 + 1, $y + 1);
|
|
$pdf->Cell($col4 - 2, 3, 'Revision', 0, 0, 'L');
|
|
|
|
// Row 4: Values
|
|
$pdf->SetFont('dejavusans', '', 8);
|
|
$pdf->SetXY($titleBlockX + 1, $y + 4);
|
|
$pdf->Cell($col1 - 2, 4, dol_trunc($user->getFullName($langs), 15), 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + 1, $y + 4);
|
|
$address = trim($societe->address.' '.$societe->zip.' '.$societe->town);
|
|
$pdf->Cell($col2 - 2, 4, dol_trunc($address, 25), 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + 1, $y + 4);
|
|
$pdf->Cell($col3 - 2, 4, $anlage->type_label ?: '-', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + $col3 + 1, $y + 4);
|
|
$pdf->Cell($col4 - 2, 4, 'A', 0, 0, 'L');
|
|
|
|
// Row 5: Equipment count
|
|
$y = $titleBlockY + (4 * $rowHeight);
|
|
$pdf->SetFont('dejavusans', '', 6);
|
|
$pdf->SetXY($titleBlockX + 1, $y + 1);
|
|
$pdf->Cell($col1 - 2, 3, 'Komponenten', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + 1, $y + 1);
|
|
$pdf->Cell($col2 - 2, 3, 'Verbindungen', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + 1, $y + 1);
|
|
$pdf->Cell($col3 - 2, 3, 'Hutschienen', 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + $col3 + 1, $y + 1);
|
|
$pdf->Cell($col4 - 2, 3, 'Format', 0, 0, 'L');
|
|
|
|
$pdf->SetFont('dejavusans', '', 8);
|
|
$pdf->SetXY($titleBlockX + 1, $y + 4);
|
|
$pdf->Cell($col1 - 2, 4, count($equipmentList), 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + 1, $y + 4);
|
|
$pdf->Cell($col2 - 2, 4, count($connections), 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + 1, $y + 4);
|
|
$pdf->Cell($col3 - 2, 4, count($carriers), 0, 0, 'L');
|
|
$pdf->SetXY($titleBlockX + $col1 + $col2 + $col3 + 1, $y + 4);
|
|
$pdf->Cell($col4 - 2, 4, $format.' '.$orientation, 0, 0, 'L');
|
|
|
|
// Row 6: Norm reference
|
|
$y = $titleBlockY + (5 * $rowHeight);
|
|
$pdf->SetFont('dejavusans', '', 6);
|
|
$pdf->SetXY($titleBlockX + 1, $y + 2);
|
|
$pdf->Cell($titleBlockWidth - 2, 4, 'Erstellt nach DIN EN 61082 / DIN EN 81346', 0, 0, 'C');
|
|
|
|
// Row 7: Company info
|
|
$y = $titleBlockY + (6 * $rowHeight);
|
|
$pdf->SetFont('dejavusans', 'B', 7);
|
|
$pdf->SetXY($titleBlockX + 1, $y + 2);
|
|
$pdf->Cell($titleBlockWidth - 2, 4, $mysoc->name, 0, 0, 'C');
|
|
|
|
// ============================================
|
|
// Draw the Schematic Content Area
|
|
// ============================================
|
|
|
|
$schematicX = 10;
|
|
$schematicY = 10;
|
|
$schematicWidth = $pageWidth - 20;
|
|
$schematicHeight = $titleBlockY - 15;
|
|
|
|
// Draw frame around schematic area
|
|
$pdf->SetDrawColor(0, 0, 0);
|
|
$pdf->SetLineWidth(0.3);
|
|
$pdf->Rect($schematicX, $schematicY, $schematicWidth, $schematicHeight);
|
|
|
|
// If SVG content provided, embed it
|
|
if (!empty($svgContent)) {
|
|
// Clean SVG for TCPDF
|
|
$svgContent = preg_replace('/<\?xml[^>]*\?>/', '', $svgContent);
|
|
$svgContent = preg_replace('/<!DOCTYPE[^>]*>/', '', $svgContent);
|
|
|
|
// Try to embed SVG
|
|
try {
|
|
// Scale SVG to fit in schematic area
|
|
$pdf->ImageSVG('@'.$svgContent, $schematicX + 2, $schematicY + 2, $schematicWidth - 4, $schematicHeight - 4, '', '', '', 0, false);
|
|
} catch (Exception $e) {
|
|
// SVG embedding failed - draw placeholder
|
|
$pdf->SetFont('dejavusans', 'I', 10);
|
|
$pdf->SetXY($schematicX + 10, $schematicY + 10);
|
|
$pdf->Cell(0, 10, 'SVG konnte nicht eingebettet werden: '.$e->getMessage(), 0, 1);
|
|
}
|
|
} else {
|
|
// Draw schematic manually if no SVG provided
|
|
drawSchematicContent($pdf, $carriers, $equipmentList, $connections, $schematicX, $schematicY, $schematicWidth, $schematicHeight);
|
|
}
|
|
|
|
// ============================================
|
|
// Add Wiring List on second page (Verdrahtungsliste)
|
|
// ============================================
|
|
|
|
if (count($connections) > 0) {
|
|
$pdf->AddPage($orientation, array($pageWidth, $pageHeight));
|
|
|
|
// Title
|
|
$pdf->SetFont('dejavusans', 'B', 14);
|
|
$pdf->SetXY(10, 10);
|
|
$pdf->Cell(0, 8, 'VERDRAHTUNGSLISTE / KLEMMENPLAN', 0, 1, 'L');
|
|
|
|
$pdf->SetFont('dejavusans', '', 9);
|
|
$pdf->SetXY(10, 18);
|
|
$pdf->Cell(0, 5, $anlage->label.' - '.$societe->name, 0, 1, 'L');
|
|
|
|
// Table header
|
|
$pdf->SetY(28);
|
|
$pdf->SetFont('dejavusans', 'B', 8);
|
|
$pdf->SetFillColor(220, 220, 220);
|
|
|
|
$colWidths = array(15, 35, 25, 35, 25, 25, 30, 30);
|
|
$headers = array('Nr.', 'Von (Quelle)', 'Klemme', 'Nach (Ziel)', 'Klemme', 'Typ', 'Leitung', 'Bemerkung');
|
|
|
|
$x = 10;
|
|
for ($i = 0; $i < count($headers); $i++) {
|
|
$pdf->SetXY($x, 28);
|
|
$pdf->Cell($colWidths[$i], 6, $headers[$i], 1, 0, 'C', true);
|
|
$x += $colWidths[$i];
|
|
}
|
|
|
|
// Table content
|
|
$pdf->SetFont('dejavusans', '', 7);
|
|
$y = 34;
|
|
$lineNum = 1;
|
|
|
|
// Build equipment lookup
|
|
$eqLookup = array();
|
|
foreach ($equipmentList as $eq) {
|
|
$eqLookup[$eq->id] = $eq;
|
|
}
|
|
|
|
foreach ($connections as $conn) {
|
|
// Skip rails/busbars in wiring list (they're separate)
|
|
if ($conn->is_rail) continue;
|
|
|
|
$sourceName = '-';
|
|
$sourceTerminal = $conn->source_terminal ?: '-';
|
|
$targetName = '-';
|
|
$targetTerminal = $conn->target_terminal ?: '-';
|
|
|
|
if ($conn->fk_source && isset($eqLookup[$conn->fk_source])) {
|
|
$sourceName = $eqLookup[$conn->fk_source]->label ?: $eqLookup[$conn->fk_source]->type_label_short;
|
|
}
|
|
if ($conn->fk_target && isset($eqLookup[$conn->fk_target])) {
|
|
$targetName = $eqLookup[$conn->fk_target]->label ?: $eqLookup[$conn->fk_target]->type_label_short;
|
|
}
|
|
|
|
// Connection type / medium
|
|
$connType = $conn->connection_type ?: '-';
|
|
$medium = trim($conn->medium_type.' '.$conn->medium_spec);
|
|
if (empty($medium)) $medium = '-';
|
|
|
|
$remark = $conn->output_label ?: '';
|
|
|
|
if ($y > $pageHeight - 25) {
|
|
// New page
|
|
$pdf->AddPage($orientation, array($pageWidth, $pageHeight));
|
|
$y = 10;
|
|
|
|
// Repeat header
|
|
$pdf->SetFont('dejavusans', 'B', 8);
|
|
$x = 10;
|
|
for ($i = 0; $i < count($headers); $i++) {
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($colWidths[$i], 6, $headers[$i], 1, 0, 'C', true);
|
|
$x += $colWidths[$i];
|
|
}
|
|
$y += 6;
|
|
$pdf->SetFont('dejavusans', '', 7);
|
|
}
|
|
|
|
$x = 10;
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($colWidths[0], 5, $lineNum, 1, 0, 'C');
|
|
$x += $colWidths[0];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($colWidths[1], 5, dol_trunc($sourceName, 18), 1, 0, 'L');
|
|
$x += $colWidths[1];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($colWidths[2], 5, $sourceTerminal, 1, 0, 'C');
|
|
$x += $colWidths[2];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($colWidths[3], 5, dol_trunc($targetName, 18), 1, 0, 'L');
|
|
$x += $colWidths[3];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($colWidths[4], 5, $targetTerminal, 1, 0, 'C');
|
|
$x += $colWidths[4];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($colWidths[5], 5, $connType, 1, 0, 'C');
|
|
$x += $colWidths[5];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($colWidths[6], 5, dol_trunc($medium, 15), 1, 0, 'L');
|
|
$x += $colWidths[6];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($colWidths[7], 5, dol_trunc($remark, 15), 1, 0, 'L');
|
|
|
|
$y += 5;
|
|
$lineNum++;
|
|
}
|
|
|
|
// Add busbars section if any
|
|
$busbars = array_filter($connections, function($c) { return $c->is_rail; });
|
|
if (count($busbars) > 0) {
|
|
$y += 10;
|
|
if ($y > $pageHeight - 40) {
|
|
$pdf->AddPage($orientation, array($pageWidth, $pageHeight));
|
|
$y = 10;
|
|
}
|
|
|
|
$pdf->SetFont('dejavusans', 'B', 10);
|
|
$pdf->SetXY(10, $y);
|
|
$pdf->Cell(0, 6, 'SAMMELSCHIENEN / PHASENSCHIENEN', 0, 1, 'L');
|
|
$y += 8;
|
|
|
|
$pdf->SetFont('dejavusans', 'B', 8);
|
|
$bbHeaders = array('Nr.', 'Bezeichnung', 'Typ', 'Von TE', 'Bis TE', 'Phasen', 'Ausnahmen');
|
|
$bbWidths = array(15, 50, 30, 20, 20, 30, 50);
|
|
|
|
$x = 10;
|
|
for ($i = 0; $i < count($bbHeaders); $i++) {
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($bbWidths[$i], 6, $bbHeaders[$i], 1, 0, 'C', true);
|
|
$x += $bbWidths[$i];
|
|
}
|
|
$y += 6;
|
|
|
|
$pdf->SetFont('dejavusans', '', 7);
|
|
$bbNum = 1;
|
|
foreach ($busbars as $bb) {
|
|
$x = 10;
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($bbWidths[0], 5, $bbNum, 1, 0, 'C');
|
|
$x += $bbWidths[0];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($bbWidths[1], 5, $bb->output_label ?: 'Sammelschiene '.$bbNum, 1, 0, 'L');
|
|
$x += $bbWidths[1];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($bbWidths[2], 5, $bb->connection_type ?: '-', 1, 0, 'C');
|
|
$x += $bbWidths[2];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($bbWidths[3], 5, $bb->rail_start_te ?: '-', 1, 0, 'C');
|
|
$x += $bbWidths[3];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($bbWidths[4], 5, $bb->rail_end_te ?: '-', 1, 0, 'C');
|
|
$x += $bbWidths[4];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($bbWidths[5], 5, $bb->rail_phases ?: '-', 1, 0, 'C');
|
|
$x += $bbWidths[5];
|
|
|
|
$pdf->SetXY($x, $y);
|
|
$pdf->Cell($bbWidths[6], 5, $bb->excluded_te ?: '-', 1, 0, 'L');
|
|
|
|
$y += 5;
|
|
$bbNum++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Output PDF
|
|
$filename = 'Leitungslaufplan_'.dol_sanitizeFileName($anlage->label).'_'.date('Y-m-d').'.pdf';
|
|
$pdf->Output($filename, 'D');
|
|
|
|
/**
|
|
* Draw schematic content directly in PDF
|
|
* Shows only the actual equipment and connections from the database (what was drawn in the editor)
|
|
*/
|
|
function drawSchematicContent(&$pdf, $carriers, $equipment, $connections, $startX, $startY, $width, $height) {
|
|
// Phase colors (DIN VDE compliant)
|
|
$phaseColors = array(
|
|
'L1' => array(139, 69, 19), // Brown
|
|
'L2' => array(0, 0, 0), // Black
|
|
'L3' => array(128, 128, 128), // Gray
|
|
'N' => array(0, 102, 204), // Blue
|
|
'PE' => array(0, 128, 0) // Green (simplified from green-yellow)
|
|
);
|
|
|
|
// Layout constants
|
|
$teWidth = 10; // mm per TE
|
|
$equipmentStartY = $startY + 20;
|
|
$blockWidth = 8;
|
|
$blockHeight = 20;
|
|
|
|
// Calculate total width needed
|
|
$maxTE = 0;
|
|
foreach ($carriers as $carrier) {
|
|
$maxTE = max($maxTE, $carrier->total_te ?: 12);
|
|
}
|
|
$contentWidth = min($width - 40, $maxTE * $teWidth + 40);
|
|
$contentStartX = $startX + 20;
|
|
|
|
// ========================================
|
|
// Draw equipment and connections
|
|
// ========================================
|
|
$carrierIndex = 0;
|
|
foreach ($carriers as $carrier) {
|
|
$carrierY = $equipmentStartY + $carrierIndex * 50;
|
|
$carrierX = $contentStartX;
|
|
$totalTE = $carrier->total_te ?: 12;
|
|
|
|
// Carrier label
|
|
$pdf->SetFont('dejavusans', '', 6);
|
|
$pdf->SetTextColor(100, 100, 100);
|
|
$pdf->SetXY($carrierX - 15, $carrierY + $blockHeight / 2 - 2);
|
|
$pdf->Cell(12, 4, $carrier->label ?: 'H'.($carrierIndex+1), 0, 0, 'R');
|
|
|
|
// Get equipment on this carrier
|
|
$carrierEquipment = array_filter($equipment, function($eq) use ($carrier) {
|
|
return $eq->fk_carrier == $carrier->id;
|
|
});
|
|
|
|
// Get busbars for this carrier
|
|
$carrierBusbars = array_filter($connections, function($c) use ($carrier) {
|
|
return $c->is_rail && $c->fk_carrier == $carrier->id;
|
|
});
|
|
|
|
// Sort equipment by position
|
|
usort($carrierEquipment, function($a, $b) {
|
|
return ($a->position_te ?: 1) - ($b->position_te ?: 1);
|
|
});
|
|
|
|
// Draw each equipment
|
|
foreach ($carrierEquipment as $eq) {
|
|
$eqPosTE = $eq->position_te ?: 1;
|
|
$eqWidthTE = $eq->width_te ?: 1;
|
|
$eqX = $carrierX + ($eqPosTE - 1) * $teWidth;
|
|
$eqWidth = $eqWidthTE * $teWidth - 2;
|
|
|
|
// Equipment block
|
|
$color = $eq->type_color ?: '#3498db';
|
|
list($r, $g, $b) = sscanf($color, "#%02x%02x%02x");
|
|
$pdf->SetFillColor($r ?: 52, $g ?: 152, $b ?: 219);
|
|
$pdf->Rect($eqX, $carrierY, $eqWidth, $blockHeight, 'F');
|
|
|
|
// Equipment label
|
|
$pdf->SetFont('dejavusans', 'B', 5);
|
|
$pdf->SetTextColor(255, 255, 255);
|
|
$label = $eq->type_label_short ?: $eq->label;
|
|
$pdf->SetXY($eqX, $carrierY + 3);
|
|
$pdf->Cell($eqWidth, 4, dol_trunc($label, 8), 0, 0, 'C');
|
|
|
|
// Second line label
|
|
if ($eq->label && $eq->type_label_short) {
|
|
$pdf->SetFont('dejavusans', '', 4);
|
|
$pdf->SetXY($eqX, $carrierY + 8);
|
|
$pdf->Cell($eqWidth, 3, dol_trunc($eq->label, 10), 0, 0, 'C');
|
|
}
|
|
|
|
$pdf->SetTextColor(0, 0, 0);
|
|
|
|
// Consumer label below equipment
|
|
$pdf->SetFont('dejavusans', '', 5);
|
|
$pdf->SetTextColor(80, 80, 80);
|
|
$pdf->SetXY($eqX - 2, $carrierY + $blockHeight + 1);
|
|
$consumerLabel = $eq->label ?: '';
|
|
$pdf->Cell($eqWidth + 4, 4, dol_trunc($consumerLabel, 12), 0, 0, 'C');
|
|
}
|
|
|
|
// Draw busbars (Phasenschienen) for this carrier
|
|
foreach ($carrierBusbars as $busbar) {
|
|
$busbarStartTE = $busbar->rail_start_te ?: 1;
|
|
$busbarEndTE = $busbar->rail_end_te ?: $busbarStartTE;
|
|
$busbarX = $carrierX + ($busbarStartTE - 1) * $teWidth;
|
|
$busbarWidth = ($busbarEndTE - $busbarStartTE + 1) * $teWidth;
|
|
$busbarY = $carrierY - 5;
|
|
|
|
// Busbar color
|
|
$phase = $busbar->rail_phases ?: $busbar->connection_type ?: 'L1';
|
|
$color = $phaseColors[$phase] ?? array(200, 100, 50);
|
|
$pdf->SetFillColor($color[0], $color[1], $color[2]);
|
|
$pdf->Rect($busbarX, $busbarY, $busbarWidth, 3, 'F');
|
|
|
|
// Draw vertical taps from busbar to equipment
|
|
$pdf->SetDrawColor($color[0], $color[1], $color[2]);
|
|
for ($te = $busbarStartTE; $te <= $busbarEndTE; $te++) {
|
|
// Check if there's equipment at this TE
|
|
$hasEquipment = false;
|
|
foreach ($carrierEquipment as $eq) {
|
|
$eqStart = $eq->position_te ?: 1;
|
|
$eqEnd = $eqStart + ($eq->width_te ?: 1) - 1;
|
|
if ($te >= $eqStart && $te <= $eqEnd) {
|
|
$hasEquipment = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($hasEquipment) {
|
|
$tapX = $carrierX + ($te - 1) * $teWidth + $teWidth / 2;
|
|
$pdf->Line($tapX, $busbarY + 3, $tapX, $carrierY);
|
|
}
|
|
}
|
|
|
|
// Busbar label
|
|
$pdf->SetFont('dejavusans', 'B', 5);
|
|
$pdf->SetTextColor(255, 255, 255);
|
|
$pdf->SetXY($busbarX, $busbarY - 0.5);
|
|
$pdf->Cell($busbarWidth, 4, $phase, 0, 0, 'C');
|
|
}
|
|
|
|
// ========================================
|
|
// Draw Inputs (Anschlusspunkte) and Outputs (Abgänge)
|
|
// ========================================
|
|
|
|
// Get non-rail connections for this carrier's equipment
|
|
$carrierEqIds = array_map(function($eq) { return $eq->id; }, $carrierEquipment);
|
|
|
|
foreach ($connections as $conn) {
|
|
if ($conn->is_rail) continue;
|
|
|
|
// ANSCHLUSSPUNKT (Input) - fk_source is NULL, fk_target exists
|
|
if (empty($conn->fk_source) && !empty($conn->fk_target)) {
|
|
// Find target equipment
|
|
$targetEq = null;
|
|
foreach ($carrierEquipment as $eq) {
|
|
if ($eq->id == $conn->fk_target) {
|
|
$targetEq = $eq;
|
|
break;
|
|
}
|
|
}
|
|
if (!$targetEq) continue;
|
|
|
|
$eqPosTE = $targetEq->position_te ?: 1;
|
|
$eqWidthTE = $targetEq->width_te ?: 1;
|
|
$eqCenterX = $carrierX + ($eqPosTE - 1) * $teWidth + ($eqWidthTE * $teWidth) / 2;
|
|
$lineStartY = $carrierY - 18;
|
|
$lineEndY = $carrierY;
|
|
|
|
// Phase color
|
|
$phase = $conn->connection_type ?: 'L1';
|
|
$color = $phaseColors[$phase] ?? array(100, 100, 100);
|
|
$pdf->SetDrawColor($color[0], $color[1], $color[2]);
|
|
$pdf->SetFillColor($color[0], $color[1], $color[2]);
|
|
|
|
// Vertical line from top
|
|
$pdf->Line($eqCenterX, $lineStartY, $eqCenterX, $lineEndY);
|
|
|
|
// Circle at top (source indicator)
|
|
$pdf->Circle($eqCenterX, $lineStartY, 1.5, 0, 360, 'F');
|
|
|
|
// Phase label
|
|
$pdf->SetFont('dejavusans', 'B', 7);
|
|
$pdf->SetTextColor($color[0], $color[1], $color[2]);
|
|
$pdf->SetXY($eqCenterX - 5, $lineStartY - 5);
|
|
$pdf->Cell(10, 4, $phase, 0, 0, 'C');
|
|
|
|
// Optional label
|
|
if (!empty($conn->output_label)) {
|
|
$pdf->SetFont('dejavusans', '', 5);
|
|
$pdf->SetTextColor(100, 100, 100);
|
|
$pdf->SetXY($eqCenterX + 3, $lineStartY - 4);
|
|
$pdf->Cell(20, 3, dol_trunc($conn->output_label, 12), 0, 0, 'L');
|
|
}
|
|
}
|
|
|
|
// ABGANG (Output) - fk_source exists, fk_target is NULL
|
|
if (!empty($conn->fk_source) && empty($conn->fk_target)) {
|
|
// Find source equipment
|
|
$sourceEq = null;
|
|
foreach ($carrierEquipment as $eq) {
|
|
if ($eq->id == $conn->fk_source) {
|
|
$sourceEq = $eq;
|
|
break;
|
|
}
|
|
}
|
|
if (!$sourceEq) continue;
|
|
|
|
$eqPosTE = $sourceEq->position_te ?: 1;
|
|
$eqWidthTE = $sourceEq->width_te ?: 1;
|
|
$eqCenterX = $carrierX + ($eqPosTE - 1) * $teWidth + ($eqWidthTE * $teWidth) / 2;
|
|
$lineStartY = $carrierY + $blockHeight;
|
|
$lineLength = 18;
|
|
$lineEndY = $lineStartY + $lineLength;
|
|
|
|
// Phase color
|
|
$phase = $conn->connection_type ?: 'L1N';
|
|
$color = $phaseColors[$phase] ?? $phaseColors['L1'] ?? array(139, 69, 19);
|
|
$pdf->SetDrawColor($color[0], $color[1], $color[2]);
|
|
$pdf->SetFillColor($color[0], $color[1], $color[2]);
|
|
|
|
// Vertical line going down
|
|
$pdf->Line($eqCenterX, $lineStartY, $eqCenterX, $lineEndY);
|
|
|
|
// Arrow at end
|
|
$pdf->Polygon(array(
|
|
$eqCenterX - 1.5, $lineEndY - 2,
|
|
$eqCenterX, $lineEndY,
|
|
$eqCenterX + 1.5, $lineEndY - 2
|
|
), 'F');
|
|
|
|
// Left label: Bezeichnung (rotated text not easy in TCPDF, use horizontal)
|
|
if (!empty($conn->output_label)) {
|
|
$pdf->SetFont('dejavusans', 'B', 5);
|
|
$pdf->SetTextColor(0, 0, 0);
|
|
$pdf->SetXY($eqCenterX - 15, $lineEndY + 1);
|
|
$pdf->Cell(30, 3, dol_trunc($conn->output_label, 15), 0, 0, 'C');
|
|
}
|
|
|
|
// Right label: Kabeltyp + Größe
|
|
$cableInfo = trim(($conn->medium_type ?: '') . ' ' . ($conn->medium_spec ?: ''));
|
|
if (!empty($cableInfo)) {
|
|
$pdf->SetFont('dejavusans', '', 4);
|
|
$pdf->SetTextColor(100, 100, 100);
|
|
$pdf->SetXY($eqCenterX - 15, $lineEndY + 4);
|
|
$pdf->Cell(30, 3, dol_trunc($cableInfo, 18), 0, 0, 'C');
|
|
}
|
|
|
|
// Phase type
|
|
$pdf->SetFont('dejavusans', 'B', 5);
|
|
$pdf->SetTextColor($color[0], $color[1], $color[2]);
|
|
$pdf->SetXY($eqCenterX - 5, $lineEndY + 7);
|
|
$pdf->Cell(10, 3, $phase, 0, 0, 'C');
|
|
}
|
|
}
|
|
|
|
$carrierIndex++;
|
|
}
|
|
|
|
$pdf->SetTextColor(0, 0, 0);
|
|
|
|
// ========================================
|
|
// Legend - show phase colors used in busbars
|
|
// ========================================
|
|
$legendY = $startY + $height - 20;
|
|
$pdf->SetFont('dejavusans', '', 6);
|
|
$pdf->SetXY($startX + 5, $legendY);
|
|
$pdf->Cell(0, 4, 'Phasenfarben nach DIN VDE:', 0, 1, 'L');
|
|
|
|
$legendX = $startX + 5;
|
|
$phases = array('L1', 'L2', 'L3', 'N', 'PE');
|
|
foreach ($phases as $idx => $phase) {
|
|
$color = $phaseColors[$phase];
|
|
$pdf->SetFillColor($color[0], $color[1], $color[2]);
|
|
$pdf->Rect($legendX + $idx * 25, $legendY + 5, 8, 3, 'F');
|
|
$pdf->SetTextColor($color[0], $color[1], $color[2]);
|
|
$pdf->SetXY($legendX + $idx * 25 + 10, $legendY + 4);
|
|
$pdf->Cell(12, 4, $phase, 0, 0, 'L');
|
|
}
|
|
|
|
$pdf->SetTextColor(0, 0, 0);
|
|
}
|