- Menü unter Einkauf > Lieferantenbestellungen statt eigenes Top-Menü - ADL-Buttons auf Produkt-Lieferantenpreisen per Hook (pricesuppliercard) - Admin-Seite: Großhändler-Schnellübersicht mit Version-Check - Dashboard: Shop-öffnen-Button (LI-Action) - Neue Datei: class/actions_idsconnect.class.php Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
338 lines
14 KiB
PHP
Executable file
338 lines
14 KiB
PHP
Executable file
<?php
|
|
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*/
|
|
|
|
/**
|
|
* \file idsconnect/mockserver.php
|
|
* \ingroup idsconnect
|
|
* \brief Mock-Server der einen Großhandels-Shop simuliert
|
|
*
|
|
* Dieser Server empfängt IDS Connect Anfragen und simuliert einen Shop.
|
|
* Damit können alle Funktionen getestet werden, ohne echte Bestellungen auszulösen.
|
|
*/
|
|
|
|
// Dolibarr laden (ohne Login für den Mock-Server)
|
|
define('NOLOGIN', 1);
|
|
define('NOCSRFCHECK', 1);
|
|
define('NOREQUIREMENU', 1);
|
|
|
|
$res = 0;
|
|
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
|
|
$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
|
|
}
|
|
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME'];
|
|
$tmp2 = realpath(__FILE__);
|
|
$i = strlen($tmp) - 1;
|
|
$j = strlen($tmp2) - 1;
|
|
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
|
|
$i--;
|
|
$j--;
|
|
}
|
|
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
|
|
$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
|
|
}
|
|
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
|
|
$res = @include dirname(substr($tmp, 0, ($i + 1)))."/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");
|
|
}
|
|
|
|
// Nur im Testmodus erreichbar
|
|
if (!getDolGlobalInt('IDSCONNECT_TESTMODE')) {
|
|
http_response_code(403);
|
|
die("Mock-Server ist nur im Testmodus verfügbar");
|
|
}
|
|
|
|
// IDS-Parameter aus POST lesen
|
|
$kndnr = GETPOST('kndnr', 'alphanohtml') ?: '';
|
|
$name_kunde = GETPOST('name_kunde', 'alphanohtml') ?: '';
|
|
$pw_kunde = GETPOST('pw_kunde', 'none') ?: '';
|
|
$version = GETPOST('version', 'alphanohtml') ?: '2.5';
|
|
$ids_action = GETPOST('action', 'alpha') ?: '';
|
|
$hookurl = GETPOST('hookurl', 'alphanohtml') ?: '';
|
|
$warenkorb_xml = GETPOST('warenkorb', 'none') ?: '';
|
|
$artikelnr = GETPOST('artikelnr', 'alphanohtml') ?: '';
|
|
|
|
// Mock-Server Action bestimmen
|
|
$mock_action = GETPOST('mock_action', 'alpha') ?: '';
|
|
|
|
// Beispiel-Artikel für den Mock-Shop
|
|
$mock_articles = array(
|
|
array('nr' => '1234567', 'bezeichnung' => 'Leitungsschutzschalter B16 1-polig', 'preis' => 5.42, 'einheit' => 'STK', 'hersteller' => 'Hager', 'ean' => '3250613160012'),
|
|
array('nr' => '2345678', 'bezeichnung' => 'FI-Schutzschalter 40A 30mA 4-polig', 'preis' => 28.90, 'einheit' => 'STK', 'hersteller' => 'ABB', 'ean' => '7612271443526'),
|
|
array('nr' => '3456789', 'bezeichnung' => 'NYM-J 3x1,5 mm² (100m Ring)', 'preis' => 62.50, 'einheit' => 'STK', 'hersteller' => 'Lapp', 'ean' => '4044774881328'),
|
|
array('nr' => '4567890', 'bezeichnung' => 'Schalterdose UP D=60mm', 'preis' => 0.35, 'einheit' => 'STK', 'hersteller' => 'Kaiser', 'ean' => '4013456000216'),
|
|
array('nr' => '5678901', 'bezeichnung' => 'Zählerschrank 1-Feld komplett', 'preis' => 189.00, 'einheit' => 'STK', 'hersteller' => 'Hager', 'ean' => '3250616167483'),
|
|
array('nr' => '6789012', 'bezeichnung' => 'Wallbox 11kW mit Ladesteckdose Typ 2', 'preis' => 495.00, 'einheit' => 'STK', 'hersteller' => 'ABL', 'ean' => '4015141000001'),
|
|
array('nr' => '7890123', 'bezeichnung' => 'SLS-Schalter E-Charakteristik 35A 1-polig', 'preis' => 22.80, 'einheit' => 'STK', 'hersteller' => 'Hager', 'ean' => '3250613211363'),
|
|
array('nr' => '8901234', 'bezeichnung' => 'Überspannungsschutz Typ 2 TN-S', 'preis' => 78.50, 'einheit' => 'STK', 'hersteller' => 'Dehn', 'ean' => '4013364108530'),
|
|
);
|
|
|
|
|
|
// ============================================================
|
|
// Warenkorb an HOOKURL zurücksenden
|
|
// ============================================================
|
|
if ($mock_action === 'send_cart' && !empty($hookurl)) {
|
|
$cart_items = array();
|
|
if (!empty($_POST['cart_items']) && is_array($_POST['cart_items'])) {
|
|
foreach ($_POST['cart_items'] as $idx => $item) {
|
|
$qty = (int) ($item['qty'] ?? 0);
|
|
if ($qty > 0 && isset($mock_articles[$idx])) {
|
|
$art = $mock_articles[$idx];
|
|
$cart_items[] = array(
|
|
'nr' => $art['nr'],
|
|
'bezeichnung' => $art['bezeichnung'],
|
|
'menge' => $qty,
|
|
'einheit' => $art['einheit'],
|
|
'einzelpreis' => $art['preis'],
|
|
'ean' => $art['ean'],
|
|
'hersteller' => $art['hersteller'],
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (empty($cart_items)) {
|
|
$error_msg = 'Keine Artikel ausgewählt';
|
|
} else {
|
|
// Warenkorb-XML im IDS Connect 2.5 Format generieren
|
|
$xml = '<?xml version="1.0" encoding="UTF-8"?>'."\n";
|
|
$xml .= '<Warenkorb xmlns="http://www.itek.de/Shop-Anbindung/Warenkorb/">'."\n";
|
|
$xml .= ' <WarenkorbInfo>'."\n";
|
|
$xml .= ' <Date>'.date('Y-m-d').'</Date>'."\n";
|
|
$xml .= ' <Time>'.date('H:i:s').'</Time>'."\n";
|
|
$xml .= ' <RueckgabeKZ>Warenkorbruückgabe</RueckgabeKZ>'."\n";
|
|
$xml .= ' <Version>2.5</Version>'."\n";
|
|
$xml .= ' </WarenkorbInfo>'."\n";
|
|
$xml .= ' <Order>'."\n";
|
|
$xml .= ' <OrderInfo>'."\n";
|
|
$xml .= ' <ModeOfShipment>Lieferung</ModeOfShipment>'."\n";
|
|
$xml .= ' <Cur>EUR</Cur>'."\n";
|
|
$xml .= ' </OrderInfo>'."\n";
|
|
foreach ($cart_items as $item) {
|
|
$xml .= ' <OrderItem>'."\n";
|
|
$xml .= ' <ArtNo>'.htmlspecialchars($item['nr'], ENT_XML1).'</ArtNo>'."\n";
|
|
$xml .= ' <Qty>'.$item['menge'].'</Qty>'."\n";
|
|
$xml .= ' <QU>'.htmlspecialchars($item['einheit'], ENT_XML1).'</QU>'."\n";
|
|
$xml .= ' <Kurztext>'.htmlspecialchars($item['bezeichnung'], ENT_XML1).'</Kurztext>'."\n";
|
|
$xml .= ' <NetPrice>'.$item['einzelpreis'].'</NetPrice>'."\n";
|
|
$xml .= ' <OfferPrice>'.$item['einzelpreis'].'</OfferPrice>'."\n";
|
|
$xml .= ' <PriceBasis>1</PriceBasis>'."\n";
|
|
$xml .= ' <VAT>19</VAT>'."\n";
|
|
$xml .= ' <EAN>'.htmlspecialchars($item['ean'], ENT_XML1).'</EAN>'."\n";
|
|
$xml .= ' <ManufacturerID>'.htmlspecialchars($item['hersteller'], ENT_XML1).'</ManufacturerID>'."\n";
|
|
$xml .= ' </OrderItem>'."\n";
|
|
}
|
|
$xml .= ' </Order>'."\n";
|
|
$xml .= '</Warenkorb>';
|
|
|
|
// Per Redirect mit POST-Daten an HOOKURL senden
|
|
// Wir nutzen ein Auto-Submit-Formular (wie IDS Connect es spezifiziert)
|
|
header('Content-Type: text/html; charset=UTF-8');
|
|
echo '<!DOCTYPE html><html><head><meta charset="UTF-8">';
|
|
echo '<title>Mock-Server - Warenkorb wird gesendet...</title></head>';
|
|
echo '<body onload="document.forms[0].submit();">';
|
|
echo '<p>Warenkorb wird an Dolibarr gesendet ('.count($cart_items).' Artikel)...</p>';
|
|
echo '<form method="post" action="'.htmlspecialchars($hookurl).'" enctype="multipart/form-data">';
|
|
echo '<input type="hidden" name="warenkorb" value="'.htmlspecialchars($xml).'">';
|
|
echo '<noscript><input type="submit" value="Warenkorb senden"></noscript>';
|
|
echo '</form></body></html>';
|
|
exit;
|
|
}
|
|
}
|
|
|
|
|
|
// ============================================================
|
|
// Mock-Shop HTML ausgeben
|
|
// ============================================================
|
|
header('Content-Type: text/html; charset=UTF-8');
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>IDS Connect Mock-Server - Testshop</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; max-width: 900px; margin: 20px auto; padding: 0 20px; background: #f5f5f5; }
|
|
.header { background: #e74c3c; color: white; padding: 15px 20px; border-radius: 5px 5px 0 0; }
|
|
.header h1 { margin: 0; font-size: 20px; }
|
|
.header .badge { background: #c0392b; padding: 3px 10px; border-radius: 3px; font-size: 12px; margin-left: 10px; }
|
|
.content { background: white; padding: 20px; border-radius: 0 0 5px 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
|
|
.info { background: #ffeaa7; padding: 10px; border-radius: 3px; margin-bottom: 15px; border-left: 4px solid #fdcb6e; }
|
|
.credentials { background: #dfe6e9; padding: 10px; border-radius: 3px; margin-bottom: 15px; font-size: 13px; }
|
|
table { width: 100%; border-collapse: collapse; margin: 15px 0; }
|
|
th { background: #2c3e50; color: white; padding: 10px; text-align: left; }
|
|
td { padding: 8px 10px; border-bottom: 1px solid #eee; }
|
|
tr:hover { background: #f8f9fa; }
|
|
input[type="number"] { width: 60px; padding: 5px; border: 1px solid #ccc; border-radius: 3px; }
|
|
.btn { background: #27ae60; color: white; padding: 10px 25px; border: none; border-radius: 5px; cursor: pointer; font-size: 14px; }
|
|
.btn:hover { background: #219a52; }
|
|
.btn-cancel { background: #95a5a6; }
|
|
.btn-cancel:hover { background: #7f8c8d; }
|
|
.price { text-align: right; font-family: monospace; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="header">
|
|
<h1>🔌 Mock-Elektrogroßhandel <span class="badge">TESTMODUS</span></h1>
|
|
</div>
|
|
<div class="content">
|
|
<div class="info">
|
|
<strong>⚠️ Dies ist ein Testshop!</strong> Keine echten Bestellungen werden ausgelöst.
|
|
Alle Daten sind Beispieldaten für Entwicklungszwecke.
|
|
</div>
|
|
|
|
<?php if (!empty($error_msg)): ?>
|
|
<div style="background:#fab1a0; padding:10px; border-radius:3px; margin-bottom:15px;">
|
|
<strong>Fehler:</strong> <?php echo htmlspecialchars($error_msg); ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="credentials">
|
|
<strong>Empfangene IDS-Daten:</strong>
|
|
Kundennr: <code><?php echo htmlspecialchars($kndnr); ?></code> |
|
|
Benutzer: <code><?php echo htmlspecialchars($name_kunde); ?></code> |
|
|
Version: <code><?php echo htmlspecialchars($version); ?></code> |
|
|
Action: <code><?php echo htmlspecialchars($ids_action); ?></code>
|
|
</div>
|
|
|
|
<?php if ($ids_action === 'WKS' && !empty($warenkorb_xml)): ?>
|
|
<h2>Bestellung empfangen (WKS)</h2>
|
|
<div style="background:#d4edda; padding:15px; border-radius:5px; border-left:4px solid #28a745; margin-bottom:15px;">
|
|
<strong>Bestellung erfolgreich empfangen!</strong><br>
|
|
Der Großhandel hat folgende Artikel erhalten:
|
|
</div>
|
|
<?php
|
|
// Empfangenes Warenkorb-XML parsen und anzeigen
|
|
dol_include_once('/idsconnect/class/idsconnect.class.php');
|
|
$parser = new IdsConnect($db);
|
|
$received_items = $parser->parseCartXml($warenkorb_xml);
|
|
if (is_array($received_items) && count($received_items) > 0):
|
|
?>
|
|
<table>
|
|
<tr>
|
|
<th>Art.-Nr.</th>
|
|
<th>Bezeichnung</th>
|
|
<th class="price">Einzelpreis (€)</th>
|
|
<th>Menge</th>
|
|
<th>Einheit</th>
|
|
</tr>
|
|
<?php $wks_total = 0; foreach ($received_items as $ri):
|
|
$line_total = $ri['menge'] * $ri['einzelpreis'];
|
|
$wks_total += $line_total;
|
|
?>
|
|
<tr>
|
|
<td><code><?php echo htmlspecialchars($ri['artikelnr']); ?></code></td>
|
|
<td><?php echo htmlspecialchars($ri['bezeichnung']); ?></td>
|
|
<td class="price"><?php echo number_format($ri['einzelpreis'], 2, ',', '.'); ?></td>
|
|
<td><?php echo (int)$ri['menge']; ?></td>
|
|
<td><?php echo htmlspecialchars($ri['einheit']); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<tr style="font-weight:bold; border-top:2px solid #333;">
|
|
<td colspan="4" style="text-align:right;">Gesamt netto:</td>
|
|
<td class="price"><?php echo number_format($wks_total, 2, ',', '.'); ?> €</td>
|
|
</tr>
|
|
</table>
|
|
<?php else: ?>
|
|
<p style="color:#e74c3c;">Warenkorb-XML konnte nicht geparst werden.</p>
|
|
<details>
|
|
<summary>XML-Rohdaten</summary>
|
|
<pre style="background:#f8f9fa; padding:10px; overflow:auto;"><?php echo htmlspecialchars($warenkorb_xml); ?></pre>
|
|
</details>
|
|
<?php endif; ?>
|
|
|
|
<div style="margin-top:20px; padding:15px; background:#fff3cd; border-radius:5px; border-left:4px solid #ffc107;">
|
|
<strong>Mock-Server Simulation:</strong> Im Live-Betrieb würde der Sonepar-Shop diese Bestellung entgegennehmen und verarbeiten.
|
|
</div>
|
|
|
|
<?php elseif ($ids_action === 'WKE' || empty($ids_action)): ?>
|
|
<h2>Artikel auswählen</h2>
|
|
<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
|
|
<input type="hidden" name="mock_action" value="send_cart">
|
|
<input type="hidden" name="hookurl" value="<?php echo htmlspecialchars($hookurl); ?>">
|
|
|
|
<table>
|
|
<tr>
|
|
<th>Art.-Nr.</th>
|
|
<th>Bezeichnung</th>
|
|
<th>Hersteller</th>
|
|
<th class="price">Preis (€)</th>
|
|
<th>Menge</th>
|
|
</tr>
|
|
<?php foreach ($mock_articles as $idx => $art): ?>
|
|
<tr>
|
|
<td><code><?php echo htmlspecialchars($art['nr']); ?></code></td>
|
|
<td><?php echo htmlspecialchars($art['bezeichnung']); ?></td>
|
|
<td><?php echo htmlspecialchars($art['hersteller']); ?></td>
|
|
<td class="price"><?php echo number_format($art['preis'], 2, ',', '.'); ?></td>
|
|
<td><input type="number" name="cart_items[<?php echo $idx; ?>][qty]" value="0" min="0" max="999"></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</table>
|
|
|
|
<div style="text-align:right; margin-top:15px;">
|
|
<?php if (!empty($hookurl)): ?>
|
|
<button type="submit" class="btn">🛒 Warenkorb an Dolibarr senden</button>
|
|
<?php else: ?>
|
|
<p style="color:#e74c3c;">Keine HOOKURL empfangen - Rücksendung nicht möglich.</p>
|
|
<?php endif; ?>
|
|
</div>
|
|
</form>
|
|
|
|
<?php elseif ($ids_action === 'ADL'): ?>
|
|
<h2>Artikel Deep-Link</h2>
|
|
<div style="padding:20px; background:#f8f9fa; border-radius:5px;">
|
|
<p>Angefragter Artikel: <strong><?php echo htmlspecialchars($artikelnr); ?></strong></p>
|
|
<?php
|
|
$found = false;
|
|
foreach ($mock_articles as $art) {
|
|
if ($art['nr'] === $artikelnr) {
|
|
$found = true;
|
|
echo '<table>';
|
|
echo '<tr><td><strong>Artikelnummer:</strong></td><td>'.htmlspecialchars($art['nr']).'</td></tr>';
|
|
echo '<tr><td><strong>Bezeichnung:</strong></td><td>'.htmlspecialchars($art['bezeichnung']).'</td></tr>';
|
|
echo '<tr><td><strong>Hersteller:</strong></td><td>'.htmlspecialchars($art['hersteller']).'</td></tr>';
|
|
echo '<tr><td><strong>Preis:</strong></td><td>'.number_format($art['preis'], 2, ',', '.').' €</td></tr>';
|
|
echo '<tr><td><strong>Verfügbar:</strong></td><td>✅ Auf Lager (Mock)</td></tr>';
|
|
echo '</table>';
|
|
break;
|
|
}
|
|
}
|
|
if (!$found) {
|
|
echo '<p style="color:#e74c3c;">Artikel nicht gefunden (Mock-Datenbank enthält nur Beispieldaten)</p>';
|
|
}
|
|
?>
|
|
</div>
|
|
|
|
<?php elseif ($ids_action === 'SV'): ?>
|
|
<h2>Schnittstellenversion</h2>
|
|
<p>Unterstützte IDS Connect Version: <strong>2.5</strong></p>
|
|
|
|
<?php elseif ($ids_action === 'LI'): ?>
|
|
<h2>Login-Information</h2>
|
|
<p>Login erfolgreich (Mock-Server)</p>
|
|
<p>Kundennummer: <strong><?php echo htmlspecialchars($kndnr); ?></strong></p>
|
|
<?php endif; ?>
|
|
|
|
<hr style="margin-top:20px;">
|
|
<p style="font-size:12px; color:#999;">
|
|
IDS Connect Mock-Server v1.0 | Nur für Entwicklung und Tests |
|
|
<a href="<?php echo DOL_URL_ROOT; ?>/custom/idsconnect/idsconnectindex.php">Zurück zu Dolibarr</a>
|
|
</p>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
<?php
|