fix: Datanorm-Preisvergleich mit Kupferzuschlag (v4.3)
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 <noreply@anthropic.com>
This commit is contained in:
parent
efa36ba86d
commit
953774c9f7
4 changed files with 102 additions and 7 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
|
@ -2,6 +2,20 @@
|
||||||
|
|
||||||
Alle wesentlichen Änderungen an diesem Projekt werden in dieser Datei dokumentiert.
|
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
|
## [4.2] - 2026-03-02
|
||||||
|
|
||||||
### Behoben
|
### Behoben
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,11 @@ Available in:
|
||||||
|
|
||||||
See [CHANGELOG.md](CHANGELOG.md) for detailed version history.
|
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
|
- PDF attachments now properly linked to supplier invoices via ECM database
|
||||||
- Most expensive item shown as invoice label in supplier invoice list
|
- Most expensive item shown as invoice label in supplier invoice list
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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'
|
$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'
|
// 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
|
// Url to the file with your last numberversion of this module
|
||||||
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
//$this->url_last_version = 'http://www.example.com/versionmodule.txt';
|
||||||
|
|
||||||
|
|
|
||||||
87
import.php
87
import.php
|
|
@ -1877,15 +1877,32 @@ if ($action == 'previewdatanorm' && $id > 0) {
|
||||||
// Only show suppliers that don't already have a price for this product
|
// Only show suppliers that don't already have a price for this product
|
||||||
$supplierAlternatives = array();
|
$supplierAlternatives = array();
|
||||||
$existingPriceSuppliers = 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) {
|
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;
|
$sqlExisting .= " WHERE fk_product = ".(int)$existingProductId;
|
||||||
$resExisting = $db->query($sqlExisting);
|
$resExisting = $db->query($sqlExisting);
|
||||||
if ($resExisting) {
|
if ($resExisting) {
|
||||||
while ($objEx = $db->fetch_object($resExisting)) {
|
while ($objEx = $db->fetch_object($resExisting)) {
|
||||||
$existingPriceSuppliers[$objEx->fk_soc] = true;
|
$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 = new Societe($db);
|
||||||
$altSupplier->fetch($altResult['fk_soc']);
|
$altSupplier->fetch($altResult['fk_soc']);
|
||||||
|
|
||||||
|
// Datanorm base price (per unit)
|
||||||
$altPurchasePrice = $altResult['price'];
|
$altPurchasePrice = $altResult['price'];
|
||||||
if ($altResult['price_unit'] > 1) {
|
if ($altResult['price_unit'] > 1) {
|
||||||
$altPurchasePrice = $altResult['price'] / $altResult['price_unit'];
|
$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(
|
$supplierAlternatives[] = array(
|
||||||
'datanorm_id' => $altResult['id'],
|
'datanorm_id' => $altResult['id'],
|
||||||
'fk_soc' => $altResult['fk_soc'],
|
'fk_soc' => $altResult['fk_soc'],
|
||||||
|
|
@ -1912,7 +1934,9 @@ if ($action == 'previewdatanorm' && $id > 0) {
|
||||||
'short_text1' => $altResult['short_text1'],
|
'short_text1' => $altResult['short_text1'],
|
||||||
'price' => $altResult['price'],
|
'price' => $altResult['price'],
|
||||||
'price_unit' => $altResult['price_unit'],
|
'price_unit' => $altResult['price_unit'],
|
||||||
'purchase_price' => $altPurchasePrice,
|
'purchase_price' => $altPurchasePriceWithCopper,
|
||||||
|
'datanorm_base_price' => $altPurchasePrice, // Without copper
|
||||||
|
'copper_surcharge' => $productCopperSurcharge,
|
||||||
'ean' => $altResult['ean'],
|
'ean' => $altResult['ean'],
|
||||||
'manufacturer_ref' => $altResult['manufacturer_ref'],
|
'manufacturer_ref' => $altResult['manufacturer_ref'],
|
||||||
'is_invoice_supplier' => ($altResult['fk_soc'] == $import->fk_soc),
|
'is_invoice_supplier' => ($altResult['fk_soc'] == $import->fk_soc),
|
||||||
|
|
@ -1933,7 +1957,8 @@ if ($action == 'previewdatanorm' && $id > 0) {
|
||||||
'datanorm_price' => $datanorm->price,
|
'datanorm_price' => $datanorm->price,
|
||||||
'datanorm_price_unit' => $datanorm->price_unit,
|
'datanorm_price_unit' => $datanorm->price_unit,
|
||||||
'datanorm_ean' => $datanorm->ean,
|
'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,
|
'selling_price' => $sellingPrice,
|
||||||
'copper_surcharge' => $copperSurchargeForPrice,
|
'copper_surcharge' => $copperSurchargeForPrice,
|
||||||
'existing_product_id' => $existingProductId,
|
'existing_product_id' => $existingProductId,
|
||||||
|
|
@ -2588,6 +2613,18 @@ if ($action == 'edit' && $import->id > 0) {
|
||||||
$datanormSearch = new Datanorm($db);
|
$datanormSearch = new Datanorm($db);
|
||||||
$allCatalogResults = array();
|
$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
|
// Suche mit Artikelnummer - die Funktion nutzt dann die EAN für Cross-Catalog
|
||||||
if (!empty($line->supplier_ref)) {
|
if (!empty($line->supplier_ref)) {
|
||||||
$allCatalogResults = $datanormSearch->searchByArticleNumber($line->supplier_ref, $import->fk_soc, true, 10);
|
$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 = new Societe($db);
|
||||||
$altSupplier->fetch($catalogResult['fk_soc']);
|
$altSupplier->fetch($catalogResult['fk_soc']);
|
||||||
|
|
||||||
|
// Datanorm base price (per unit)
|
||||||
$altPurchasePrice = $catalogResult['price'];
|
$altPurchasePrice = $catalogResult['price'];
|
||||||
if ($catalogResult['price_unit'] > 1) {
|
if ($catalogResult['price_unit'] > 1) {
|
||||||
$altPurchasePrice = $catalogResult['price'] / $catalogResult['price_unit'];
|
$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(
|
$missingSuppliers[] = array(
|
||||||
'datanorm_id' => $catalogResult['id'],
|
'datanorm_id' => $catalogResult['id'],
|
||||||
'fk_soc' => $catalogResult['fk_soc'],
|
'fk_soc' => $catalogResult['fk_soc'],
|
||||||
|
|
@ -2613,7 +2655,9 @@ if ($action == 'edit' && $import->id > 0) {
|
||||||
'article_number' => $catalogResult['article_number'],
|
'article_number' => $catalogResult['article_number'],
|
||||||
'price' => $catalogResult['price'],
|
'price' => $catalogResult['price'],
|
||||||
'price_unit' => $catalogResult['price_unit'],
|
'price_unit' => $catalogResult['price_unit'],
|
||||||
'purchase_price' => $altPurchasePrice,
|
'purchase_price' => $altPurchasePriceWithCopper,
|
||||||
|
'datanorm_base_price' => $altPurchasePrice, // Without copper
|
||||||
|
'copper_surcharge' => $productCopperSurcharge,
|
||||||
'ean' => $catalogResult['ean'],
|
'ean' => $catalogResult['ean'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -2862,12 +2906,30 @@ if ($action == 'edit' && $import->id > 0) {
|
||||||
print '<div class="titre" style="margin-bottom: 10px;">';
|
print '<div class="titre" style="margin-bottom: 10px;">';
|
||||||
print '<i class="fas fa-database paddingright"></i>'.$langs->trans('DatanormPreview');
|
print '<i class="fas fa-database paddingright"></i>'.$langs->trans('DatanormPreview');
|
||||||
print ' <span class="badge badge-info">'.count($datanormPreviewMatches).' '.$langs->trans('Matches').'</span>';
|
print ' <span class="badge badge-info">'.count($datanormPreviewMatches).' '.$langs->trans('Matches').'</span>';
|
||||||
|
|
||||||
|
// Filter: Kabel ausblenden (in eigenem Form für sofortiges Submit)
|
||||||
|
print '<span style="margin-left: 15px;">';
|
||||||
|
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" style="display: inline;">';
|
||||||
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||||
|
print '<input type="hidden" name="action" value="previewdatanorm">';
|
||||||
|
print '<input type="hidden" name="id" value="'.$import->id.'">';
|
||||||
|
$hideCables = GETPOST('hide_cables', 'int');
|
||||||
|
$checked = $hideCables ? ' checked' : '';
|
||||||
|
print '<label style="font-weight: normal; cursor: pointer;">';
|
||||||
|
print '<input type="checkbox" id="hide_cables" name="hide_cables" value="1"'.$checked.' onchange="this.form.submit();">';
|
||||||
|
print ' <span style="color: #666;">Kabel ausblenden</span>';
|
||||||
|
print '</label>';
|
||||||
|
print '</form>';
|
||||||
|
print '</span>';
|
||||||
print '</div>';
|
print '</div>';
|
||||||
|
|
||||||
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" id="datanorm_confirm_form">';
|
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" id="datanorm_confirm_form">';
|
||||||
print '<input type="hidden" name="token" value="'.newToken().'">';
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||||
print '<input type="hidden" name="action" value="createallfromdatanorm">';
|
print '<input type="hidden" name="action" value="createallfromdatanorm">';
|
||||||
print '<input type="hidden" name="id" value="'.$import->id.'">';
|
print '<input type="hidden" name="id" value="'.$import->id.'">';
|
||||||
|
if ($hideCables) {
|
||||||
|
print '<input type="hidden" name="hide_cables" value="1">';
|
||||||
|
}
|
||||||
|
|
||||||
print '<table class="noborder centpercent">';
|
print '<table class="noborder centpercent">';
|
||||||
print '<tr class="liste_titre">';
|
print '<tr class="liste_titre">';
|
||||||
|
|
@ -2883,7 +2945,18 @@ if ($action == 'edit' && $import->id > 0) {
|
||||||
|
|
||||||
$countCreate = 0;
|
$countCreate = 0;
|
||||||
$countAssign = 0;
|
$countAssign = 0;
|
||||||
|
$hideCables = GETPOST('hide_cables', 'int');
|
||||||
foreach ($datanormPreviewMatches as $match) {
|
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;';
|
$rowClass = ($match['action'] == 'assign') ? 'background-color: #d9edf7;' : 'background-color: #dff0d8;';
|
||||||
|
|
||||||
print '<tr class="oddeven" style="'.$rowClass.'">';
|
print '<tr class="oddeven" style="'.$rowClass.'">';
|
||||||
|
|
@ -3033,6 +3106,10 @@ if ($action == 'edit' && $import->id > 0) {
|
||||||
if ($alt['price_unit'] > 1) {
|
if ($alt['price_unit'] > 1) {
|
||||||
print '<span class="small" style="color: #666;">'.price($alt['price']).'/'.$alt['price_unit'].'</span><br>';
|
print '<span class="small" style="color: #666;">'.price($alt['price']).'/'.$alt['price_unit'].'</span><br>';
|
||||||
}
|
}
|
||||||
|
// Show breakdown: Datanorm base price + copper surcharge
|
||||||
|
if (!empty($alt['copper_surcharge']) && $alt['copper_surcharge'] > 0) {
|
||||||
|
print '<span class="small" style="color: #666;">'.price($alt['datanorm_base_price']).' + '.price($alt['copper_surcharge']).' Kupfer</span><br>';
|
||||||
|
}
|
||||||
print '<strong>'.price($alt['purchase_price']).'</strong>';
|
print '<strong>'.price($alt['purchase_price']).'</strong>';
|
||||||
print '</td>';
|
print '</td>';
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue