dolibarr.idsconnect/log_detail.php
data 5f5a389809 IDS Connect v2.2 - Menü-Integration, ADL-Hooks, Admin-Erweiterung
- 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>
2026-02-19 17:45:15 +01:00

334 lines
12 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/log_detail.php
* \ingroup idsconnect
* \brief Detailansicht eines Log-Eintrags
*/
// Dolibarr laden
$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");
}
dol_include_once('/idsconnect/class/idslog.class.php');
dol_include_once('/idsconnect/class/idssupplier.class.php');
dol_include_once('/idsconnect/lib/idsconnect.lib.php');
/**
* @var DoliDB $db
* @var Translate $langs
* @var User $user
*/
$langs->loadLangs(array("idsconnect@idsconnect"));
if (!$user->hasRight('idsconnect', 'read')) {
accessforbidden();
}
$id = GETPOSTINT('id');
if (empty($id)) {
setEventMessages('Keine Log-ID angegeben', null, 'errors');
header('Location: '.DOL_URL_ROOT.'/custom/idsconnect/log_list.php');
exit;
}
// Log laden
$log = new IdsLog($db);
$result = $log->fetch($id);
if ($result <= 0) {
setEventMessages('Log-Eintrag #'.$id.' nicht gefunden', null, 'errors');
header('Location: '.DOL_URL_ROOT.'/custom/idsconnect/log_list.php');
exit;
}
// Großhändler laden
$supplier = new IdsSupplier($db);
$supplier->fetch($log->fk_supplier);
// Benutzer laden
$userObj = new User($db);
$userObj->fetch($log->fk_user);
/*
* View
*/
llxHeader('', $langs->trans("IdsconnectLogDetail").' #'.$id, '', '', 0, 0, '', '', '', 'mod-idsconnect page-log_detail');
print load_fiche_titre($langs->trans("IdsconnectLogDetail").' #'.$id, '<a href="'.DOL_URL_ROOT.'/custom/idsconnect/log_list.php">'.$langs->trans("IdsconnectLogList").'</a>', 'fa-search');
// ============================================================
// Basis-Informationen
// ============================================================
print '<div class="underbanner clearboth"></div>';
print '<table class="border centpercent tableforfield">';
print '<tr><td class="titlefield">'.$langs->trans("ID").'</td>';
print '<td>'.$log->id.'</td></tr>';
print '<tr><td>'.$langs->trans("IdsconnectLogDate").'</td>';
print '<td>'.dol_print_date($log->date_creation, 'dayhour').'</td></tr>';
print '<tr><td>'.$langs->trans("IdsconnectLogSupplier").'</td>';
print '<td>';
if ($supplier->id > 0) {
print '<a href="'.DOL_URL_ROOT.'/custom/idsconnect/supplier_card.php?id='.$supplier->id.'">'.htmlspecialchars($supplier->label).'</a>';
print ' <span class="opacitymedium">('.htmlspecialchars($supplier->ref).')</span>';
} else {
print '<span class="opacitymedium">Großhändler #'.$log->fk_supplier.' (gelöscht?)</span>';
}
print '</td></tr>';
print '<tr><td>'.$langs->trans("IdsconnectLogUser").'</td>';
print '<td>'.($userObj->id > 0 ? $userObj->getNomUrl(1) : 'User #'.$log->fk_user).'</td></tr>';
print '<tr><td>'.$langs->trans("IdsconnectLogAction").'</td>';
print '<td><strong>'.$log->getActionLabel().'</strong> ('.$log->action_type.')</td></tr>';
print '<tr><td>'.$langs->trans("IdsconnectLogDirection").'</td>';
print '<td>'.$log->direction.'</td></tr>';
print '<tr><td>'.$langs->trans("IdsconnectLogStatus").'</td>';
print '<td>'.$log->getStatusLabel().'</td></tr>';
print '<tr><td>IP-Adresse</td>';
print '<td>'.htmlspecialchars($log->ip_address ?: '-').'</td></tr>';
if ($log->fk_commande > 0) {
print '<tr><td>Lieferantenbestellung</td>';
print '<td><a href="'.DOL_URL_ROOT.'/fourn/commande/card.php?id='.$log->fk_commande.'">#'.$log->fk_commande.'</a></td></tr>';
}
if (!empty($log->error_message)) {
print '<tr><td>Fehlermeldung</td>';
print '<td><span class="error">'.htmlspecialchars($log->error_message).'</span></td></tr>';
}
print '</table>';
// ============================================================
// Request-Daten (was wurde gesendet)
// ============================================================
if (!empty($log->request_data)) {
print '<br>';
print load_fiche_titre('Request-Daten (gesendet)', '', 'fa-arrow-up');
$request = json_decode($log->request_data, true);
if (is_array($request)) {
print '<table class="border centpercent tableforfield">';
foreach ($request as $key => $value) {
print '<tr>';
print '<td class="titlefield"><code>'.$key.'</code></td>';
print '<td>';
if (is_array($value)) {
print '<pre class="idsconnect-log-detail" style="max-height:200px">'.htmlspecialchars(json_encode($value, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)).'</pre>';
} elseif ($key === 'hookurl' || $key === 'target_url' || $key === 'shop_url') {
print '<code>'.htmlspecialchars($value).'</code>';
} elseif ($key === 'testmode') {
print $value ? '<span class="badge badge-warning">Testmodus</span>' : '<span class="badge badge-danger">LIVE</span>';
} else {
print htmlspecialchars($value);
}
print '</td></tr>';
}
print '</table>';
} else {
print '<div class="idsconnect-log-detail">'.htmlspecialchars($log->request_data).'</div>';
}
}
// ============================================================
// Response-Daten (was kam zurück)
// ============================================================
if (!empty($log->response_data)) {
print '<br>';
print load_fiche_titre('Response-Daten (empfangen)', '', 'fa-arrow-down');
$response = json_decode($log->response_data, true);
if (is_array($response)) {
// Callback-Meta-Informationen separat anzeigen
if (!empty($response['callback_meta'])) {
print '<table class="border centpercent tableforfield">';
print '<tr class="liste_titre"><td colspan="2">Callback-Informationen</td></tr>';
foreach ($response['callback_meta'] as $key => $value) {
print '<tr>';
print '<td class="titlefield"><code>'.$key.'</code></td>';
print '<td>';
if (is_array($value)) {
print htmlspecialchars(implode(', ', $value));
} else {
print htmlspecialchars($value);
}
print '</td></tr>';
}
print '</table>';
print '<br>';
}
// Empfangene Artikel anzeigen
if (!empty($response['items']) && is_array($response['items'])) {
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<th>'.$langs->trans("IdsconnectCartArticleNr").'</th>';
print '<th>'.$langs->trans("IdsconnectCartDescription").'</th>';
print '<th class="right">'.$langs->trans("IdsconnectCartQty").'</th>';
print '<th>'.$langs->trans("IdsconnectCartUnit").'</th>';
print '<th class="right">'.$langs->trans("IdsconnectCartUnitPrice").'</th>';
print '<th class="right">'.$langs->trans("IdsconnectCartTotalPrice").'</th>';
print '<th>'.$langs->trans("IdsconnectCartManufacturer").'</th>';
print '</tr>';
$total = 0;
foreach ($response['items'] as $item) {
$line_total = (float) ($item['gesamtpreis'] ?? ((float) ($item['menge'] ?? 0) * (float) ($item['einzelpreis'] ?? 0)));
$total += $line_total;
print '<tr class="oddeven">';
print '<td><code>'.htmlspecialchars($item['artikelnr'] ?? '-').'</code></td>';
print '<td>'.htmlspecialchars($item['bezeichnung'] ?? '-').'</td>';
print '<td class="right">'.((float) ($item['menge'] ?? 0)).'</td>';
print '<td>'.htmlspecialchars($item['einheit'] ?? 'STK').'</td>';
print '<td class="right">'.price($item['einzelpreis'] ?? 0).'</td>';
print '<td class="right">'.price($line_total).'</td>';
print '<td>'.htmlspecialchars($item['hersteller'] ?? '-').'</td>';
print '</tr>';
}
print '<tr class="liste_total">';
print '<td colspan="5" class="right"><strong>'.$langs->trans("Total").'</strong></td>';
print '<td class="right"><strong>'.price($total).'</strong></td>';
print '<td></td></tr>';
print '</table>';
}
// Restliche Response-Felder
$skip_keys = array('callback_meta', 'items');
$remaining = array_diff_key($response, array_flip($skip_keys));
if (!empty($remaining)) {
print '<br><table class="border centpercent tableforfield">';
print '<tr class="liste_titre"><td colspan="2">Weitere Response-Daten</td></tr>';
foreach ($remaining as $key => $value) {
print '<tr>';
print '<td class="titlefield"><code>'.$key.'</code></td>';
print '<td>';
if (is_array($value)) {
print '<pre class="idsconnect-log-detail" style="max-height:200px">'.htmlspecialchars(json_encode($value, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)).'</pre>';
} else {
print htmlspecialchars($value);
}
print '</td></tr>';
}
print '</table>';
}
} else {
print '<div class="idsconnect-log-detail">'.htmlspecialchars($log->response_data).'</div>';
}
}
// ============================================================
// Warenkorb-XML (Rohdaten)
// ============================================================
if (!empty($log->cart_xml)) {
print '<br>';
print load_fiche_titre('Warenkorb-XML ('.strlen($log->cart_xml).' Bytes)', '', 'fa-code');
// XML formatiert ausgeben
$dom = new DOMDocument('1.0');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$formatted_xml = $log->cart_xml;
if (@$dom->loadXML($log->cart_xml)) {
$formatted_xml = $dom->saveXML();
}
print '<div class="idsconnect-log-detail">';
print htmlspecialchars($formatted_xml);
print '</div>';
}
// ============================================================
// Callback-Token (für Debugging)
// ============================================================
if (!empty($log->callback_token)) {
print '<br>';
print load_fiche_titre('Callback-Token', '', 'fa-key');
print '<table class="border centpercent tableforfield">';
print '<tr><td class="titlefield">Token</td>';
print '<td><code class="small">'.htmlspecialchars($log->callback_token).'</code></td></tr>';
print '<tr><td>Token-Status</td>';
print '<td>';
if ($log->status === 'pending') {
$token_age = dol_now() - $log->date_creation;
if ($token_age < 7200) {
$remaining = 7200 - $token_age;
print '<span class="badge badge-status4">Gültig (noch '.round($remaining / 60).' Min.)</span>';
} else {
print '<span class="badge badge-status8">Abgelaufen</span>';
}
} else {
print '<span class="badge badge-status6">Eingelöst ('.$log->status.')</span>';
}
print '</td></tr>';
print '</table>';
}
// Aktionsbuttons
print '<div class="tabsAction">';
// Warenkorb prüfen / Bestellung erstellen - wenn WKE mit Artikeln und noch keine Bestellung verknüpft
if ($log->action_type === 'WKE' && $log->status === 'success' && $log->fk_commande <= 0) {
$response_check = json_decode($log->response_data, true);
if (!empty($response_check['items']) || !empty($log->cart_xml)) {
print '<a class="butAction" href="'.DOL_URL_ROOT.'/custom/idsconnect/cart_review.php?log_id='.$log->id.'">'.$langs->trans("IdsconnectCartCreateOrder").'</a>';
}
}
// Link zur verknüpften Bestellung wenn vorhanden
if ($log->fk_commande > 0) {
print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/commande/card.php?id='.$log->fk_commande.'">Bestellung #'.$log->fk_commande.' anzeigen</a>';
}
print '<a class="butAction" href="'.DOL_URL_ROOT.'/custom/idsconnect/log_list.php';
if ($log->fk_supplier > 0) {
print '?supplier_id='.$log->fk_supplier;
}
print '">'.$langs->trans("Back").'</a>';
print '</div>';
llxFooter();
$db->close();