From 953774c9f79af08fb1124989715f1db0fc24ce86 Mon Sep 17 00:00:00 2001 From: data Date: Tue, 3 Mar 2026 08:15:22 +0100 Subject: [PATCH] fix: Datanorm-Preisvergleich mit Kupferzuschlag (v4.3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Datanorm-Preisvergleich korrigiert: - Datanorm-Preise enthalten nur Materialpreis ohne Kupferzuschlag - Kupferzuschlag wird aus Produkt-Extrafields geladen und addiert - Vergleich: Datanorm+Kupfer vs. aktueller Dolibarr-Lieferantenpreis - Anzeige zeigt Aufschlüsselung: "Base-Preis + Kupfer = Gesamt" Kabel-Filter hinzugefügt: - Checkbox "Kabel ausblenden" in Datanorm-Vorschau - Filtert Kabel-Produkte basierend auf Warengruppe - Erleichtert Fokus auf Standard-Artikel Co-Authored-By: Claude Sonnet 4.5 --- CHANGELOG.md | 14 ++++ README.md | 6 +- core/modules/modImportZugferd.class.php | 2 +- import.php | 87 +++++++++++++++++++++++-- 4 files changed, 102 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 774beef..36caea9 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ Alle wesentlichen Änderungen an diesem Projekt werden in dieser Datei dokumentiert. +## [4.3] - 2026-03-03 + +### Behoben +- **Datanorm-Preisvergleich**: Korrekte Preisberechnung mit Kupferzuschlag + - Problem: Datanorm-Preise enthalten nur Materialpreis, kein Kupferzuschlag + - Lösung: Kupferzuschlag aus Produkt-Extrafields wird zu Datanorm-Preis addiert + - Vergleich jetzt: Datanorm+Kupfer vs. aktueller Dolibarr-Preis + - Zeigt Aufschlüsselung: "Datanorm-Preis + Kupferzuschlag = Gesamtpreis" + +### Hinzugefügt +- **Kabel-Filter**: Checkbox "Kabel ausblenden" in Datanorm-Vorschau + - Filtert Kabel-Produkte aus der Anzeige (basierend auf Warengruppe) + - Erleichtert Fokus auf Standard-Artikel + ## [4.2] - 2026-03-02 ### Behoben diff --git a/README.md b/README.md index a6fec4d..d7ea790 100755 --- a/README.md +++ b/README.md @@ -104,7 +104,11 @@ Available in: See [CHANGELOG.md](CHANGELOG.md) for detailed version history. -### 4.2 (Current) +### 4.3 (Current) +- Fixed Datanorm price comparison with copper surcharge calculation +- Added cable filter for Datanorm preview + +### 4.2 - PDF attachments now properly linked to supplier invoices via ECM database - Most expensive item shown as invoice label in supplier invoice list diff --git a/core/modules/modImportZugferd.class.php b/core/modules/modImportZugferd.class.php index a91f51e..7249682 100755 --- a/core/modules/modImportZugferd.class.php +++ b/core/modules/modImportZugferd.class.php @@ -76,7 +76,7 @@ class modImportZugferd extends DolibarrModules $this->editor_squarred_logo = ''; // Must be image filename into the module/img directory followed with @modulename. Example: 'myimage.png@importzugferd' // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z' - $this->version = '4.2'; + $this->version = '4.3'; // Url to the file with your last numberversion of this module //$this->url_last_version = 'http://www.example.com/versionmodule.txt'; diff --git a/import.php b/import.php index f3eb69f..552eb35 100755 --- a/import.php +++ b/import.php @@ -1877,15 +1877,32 @@ if ($action == 'previewdatanorm' && $id > 0) { // Only show suppliers that don't already have a price for this product $supplierAlternatives = array(); $existingPriceSuppliers = array(); + $currentDolibarrPrice = 0; // Current supplier price from Dolibarr - // If product exists, load existing supplier prices + // Load existing product's copper surcharge for price comparison + $productCopperSurcharge = 0; if ($existingProductId > 0) { - $sqlExisting = "SELECT fk_soc FROM ".MAIN_DB_PREFIX."product_fournisseur_price"; + $sqlExisting = "SELECT fk_soc, unitprice FROM ".MAIN_DB_PREFIX."product_fournisseur_price"; $sqlExisting .= " WHERE fk_product = ".(int)$existingProductId; $resExisting = $db->query($sqlExisting); if ($resExisting) { while ($objEx = $db->fetch_object($resExisting)) { $existingPriceSuppliers[$objEx->fk_soc] = true; + // Load current invoice supplier's Dolibarr price for comparison + if ($objEx->fk_soc == $import->fk_soc) { + $currentDolibarrPrice = (float)$objEx->unitprice; + } + } + } + + // Load copper surcharge from product extrafields + $sqlCopper = "SELECT kupferzuschlag FROM ".MAIN_DB_PREFIX."product_extrafields"; + $sqlCopper .= " WHERE fk_object = ".(int)$existingProductId; + $resCopper = $db->query($sqlCopper); + if ($resCopper && $db->num_rows($resCopper) > 0) { + $objCopper = $db->fetch_object($resCopper); + if (!empty($objCopper->kupferzuschlag) && $objCopper->kupferzuschlag > 0) { + $productCopperSurcharge = (float)$objCopper->kupferzuschlag; } } } @@ -1899,11 +1916,16 @@ if ($action == 'previewdatanorm' && $id > 0) { $altSupplier = new Societe($db); $altSupplier->fetch($altResult['fk_soc']); + // Datanorm base price (per unit) $altPurchasePrice = $altResult['price']; if ($altResult['price_unit'] > 1) { $altPurchasePrice = $altResult['price'] / $altResult['price_unit']; } + // Add copper surcharge from existing product for comparison + // Datanorm has only material price, not copper surcharge + $altPurchasePriceWithCopper = $altPurchasePrice + $productCopperSurcharge; + $supplierAlternatives[] = array( 'datanorm_id' => $altResult['id'], 'fk_soc' => $altResult['fk_soc'], @@ -1912,7 +1934,9 @@ if ($action == 'previewdatanorm' && $id > 0) { 'short_text1' => $altResult['short_text1'], 'price' => $altResult['price'], 'price_unit' => $altResult['price_unit'], - 'purchase_price' => $altPurchasePrice, + 'purchase_price' => $altPurchasePriceWithCopper, + 'datanorm_base_price' => $altPurchasePrice, // Without copper + 'copper_surcharge' => $productCopperSurcharge, 'ean' => $altResult['ean'], 'manufacturer_ref' => $altResult['manufacturer_ref'], 'is_invoice_supplier' => ($altResult['fk_soc'] == $import->fk_soc), @@ -1933,7 +1957,8 @@ if ($action == 'previewdatanorm' && $id > 0) { 'datanorm_price' => $datanorm->price, 'datanorm_price_unit' => $datanorm->price_unit, 'datanorm_ean' => $datanorm->ean, - 'purchase_price' => $purchasePrice, + 'purchase_price' => $currentDolibarrPrice, // Current Dolibarr price for comparison + 'datanorm_purchase_price' => $purchasePrice, // New Datanorm price 'selling_price' => $sellingPrice, 'copper_surcharge' => $copperSurchargeForPrice, 'existing_product_id' => $existingProductId, @@ -2588,6 +2613,18 @@ if ($action == 'edit' && $import->id > 0) { $datanormSearch = new Datanorm($db); $allCatalogResults = array(); + // Load copper surcharge from product extrafields for price comparison + $productCopperSurcharge = 0; + $sqlCopper = "SELECT kupferzuschlag FROM ".MAIN_DB_PREFIX."product_extrafields"; + $sqlCopper .= " WHERE fk_object = ".(int)$line->fk_product; + $resCopper = $db->query($sqlCopper); + if ($resCopper && $db->num_rows($resCopper) > 0) { + $objCopper = $db->fetch_object($resCopper); + if (!empty($objCopper->kupferzuschlag) && $objCopper->kupferzuschlag > 0) { + $productCopperSurcharge = (float)$objCopper->kupferzuschlag; + } + } + // Suche mit Artikelnummer - die Funktion nutzt dann die EAN für Cross-Catalog if (!empty($line->supplier_ref)) { $allCatalogResults = $datanormSearch->searchByArticleNumber($line->supplier_ref, $import->fk_soc, true, 10); @@ -2601,11 +2638,16 @@ if ($action == 'edit' && $import->id > 0) { $altSupplier = new Societe($db); $altSupplier->fetch($catalogResult['fk_soc']); + // Datanorm base price (per unit) $altPurchasePrice = $catalogResult['price']; if ($catalogResult['price_unit'] > 1) { $altPurchasePrice = $catalogResult['price'] / $catalogResult['price_unit']; } + // Add copper surcharge from existing product for comparison + // Datanorm has only material price, not copper surcharge + $altPurchasePriceWithCopper = $altPurchasePrice + $productCopperSurcharge; + $missingSuppliers[] = array( 'datanorm_id' => $catalogResult['id'], 'fk_soc' => $catalogResult['fk_soc'], @@ -2613,7 +2655,9 @@ if ($action == 'edit' && $import->id > 0) { 'article_number' => $catalogResult['article_number'], 'price' => $catalogResult['price'], 'price_unit' => $catalogResult['price_unit'], - 'purchase_price' => $altPurchasePrice, + 'purchase_price' => $altPurchasePriceWithCopper, + 'datanorm_base_price' => $altPurchasePrice, // Without copper + 'copper_surcharge' => $productCopperSurcharge, 'ean' => $catalogResult['ean'], ); } @@ -2862,12 +2906,30 @@ if ($action == 'edit' && $import->id > 0) { print '
'; print ''.$langs->trans('DatanormPreview'); print ' '.count($datanormPreviewMatches).' '.$langs->trans('Matches').''; + + // Filter: Kabel ausblenden (in eigenem Form für sofortiges Submit) + print ''; + print '
'; + print ''; + print ''; + print ''; + $hideCables = GETPOST('hide_cables', 'int'); + $checked = $hideCables ? ' checked' : ''; + print ''; + print '
'; + print '
'; print '
'; print '
'; print ''; print ''; print ''; + if ($hideCables) { + print ''; + } print ''; print ''; @@ -2883,7 +2945,18 @@ if ($action == 'edit' && $import->id > 0) { $countCreate = 0; $countAssign = 0; + $hideCables = GETPOST('hide_cables', 'int'); foreach ($datanormPreviewMatches as $match) { + // Filter: Kabel ausblenden wenn gewünscht + if ($hideCables) { + // Load Datanorm product group to check if it's a cable + $datanormObj = new Datanorm($db); + $datanormObj->fetch($match['datanorm_id']); + if (isCableProduct($datanormObj)) { + continue; // Skip cables + } + } + $rowClass = ($match['action'] == 'assign') ? 'background-color: #d9edf7;' : 'background-color: #dff0d8;'; print ''; @@ -3033,6 +3106,10 @@ if ($action == 'edit' && $import->id > 0) { if ($alt['price_unit'] > 1) { print ''.price($alt['price']).'/'.$alt['price_unit'].'
'; } + // Show breakdown: Datanorm base price + copper surcharge + if (!empty($alt['copper_surcharge']) && $alt['copper_surcharge'] > 0) { + print ''.price($alt['datanorm_base_price']).' + '.price($alt['copper_surcharge']).' Kupfer
'; + } print ''.price($alt['purchase_price']).''; print '';