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.
|
||||
|
||||
## [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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
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
|
||||
$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 '<div class="titre" style="margin-bottom: 10px;">';
|
||||
print '<i class="fas fa-database paddingright"></i>'.$langs->trans('DatanormPreview');
|
||||
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 '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" id="datanorm_confirm_form">';
|
||||
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
print '<input type="hidden" name="action" value="createallfromdatanorm">';
|
||||
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 '<tr class="liste_titre">';
|
||||
|
|
@ -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 '<tr class="oddeven" style="'.$rowClass.'">';
|
||||
|
|
@ -3033,6 +3106,10 @@ if ($action == 'edit' && $import->id > 0) {
|
|||
if ($alt['price_unit'] > 1) {
|
||||
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 '</td>';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue