fix: Datanorm-Preisvergleich mit Kupferzuschlag und Mindestmengen (v4.3)
Problem: 1. Datanorm-Preise enthielten nur Materialpreis, kein Kupferzuschlag 2. Preise wurden als Stückpreis statt Preis für Mindestmenge angezeigt Lösung: 1. Kupferzuschlag aus Dolibarr-Lieferantenpreis-Extrafields wird zu Datanorm-Preis addiert 2. Hauptpreis zeigt jetzt Preis für Mindestmenge (z.B. 147,59€/100) 3. Stückpreis wird als sekundäre Info angezeigt (1,48€/Stk.) 4. Vergleich zwischen Datanorm und aktuellem Dolibarr-Preis für gleiche Menge Beispiel: - Datanorm: 102,29€ (Material) + 45,30€ (Kupfer) = 147,59€/100 - Dolibarr aktuell: 52,00€/100 - Differenz: +95,59€ (+183%) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
848f24e7c5
commit
70354e824d
1 changed files with 96 additions and 44 deletions
140
import.php
140
import.php
|
|
@ -1881,9 +1881,10 @@ if ($action == 'previewdatanorm' && $id > 0) {
|
|||
|
||||
// Load existing product's copper surcharge for price comparison
|
||||
$productCopperSurcharge = 0;
|
||||
$currentSupplierPriceId = 0;
|
||||
if ($existingProductId > 0) {
|
||||
$sqlExisting = "SELECT fk_soc, unitprice FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
|
||||
$sqlExisting .= " WHERE fk_product = ".(int)$existingProductId;
|
||||
$sqlExisting = "SELECT pf.rowid, pf.fk_soc, pf.unitprice FROM ".MAIN_DB_PREFIX."product_fournisseur_price pf";
|
||||
$sqlExisting .= " WHERE pf.fk_product = ".(int)$existingProductId;
|
||||
$resExisting = $db->query($sqlExisting);
|
||||
if ($resExisting) {
|
||||
while ($objEx = $db->fetch_object($resExisting)) {
|
||||
|
|
@ -1891,18 +1892,21 @@ if ($action == 'previewdatanorm' && $id > 0) {
|
|||
// Load current invoice supplier's Dolibarr price for comparison
|
||||
if ($objEx->fk_soc == $import->fk_soc) {
|
||||
$currentDolibarrPrice = (float)$objEx->unitprice;
|
||||
$currentSupplierPriceId = $objEx->rowid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
// Load copper surcharge from supplier price extrafields (not product extrafields!)
|
||||
if ($currentSupplierPriceId > 0) {
|
||||
$sqlCopper = "SELECT kupferzuschlag FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
|
||||
$sqlCopper .= " WHERE fk_object = ".(int)$currentSupplierPriceId;
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1916,15 +1920,19 @@ 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'];
|
||||
}
|
||||
// Calculate unit price from Datanorm
|
||||
$priceUnit = ($altResult['price_unit'] > 0) ? $altResult['price_unit'] : 1;
|
||||
$materialPrice = $altResult['price'];
|
||||
|
||||
// Add copper surcharge from existing product for comparison
|
||||
// Datanorm has only material price, not copper surcharge
|
||||
$altPurchasePriceWithCopper = $altPurchasePrice + $productCopperSurcharge;
|
||||
// Datanorm has NO metal surcharge - use copper surcharge from Dolibarr supplier price instead
|
||||
// $productCopperSurcharge is already loaded from extrafields above
|
||||
$metalSurcharge = $productCopperSurcharge;
|
||||
|
||||
// Total price for price unit (e.g. for 100 pieces)
|
||||
$totalPriceForUnit = $materialPrice + $metalSurcharge;
|
||||
|
||||
// Unit price (price per 1 piece/meter)
|
||||
$altPurchasePrice = $totalPriceForUnit / $priceUnit;
|
||||
|
||||
$supplierAlternatives[] = array(
|
||||
'datanorm_id' => $altResult['id'],
|
||||
|
|
@ -1934,9 +1942,10 @@ if ($action == 'previewdatanorm' && $id > 0) {
|
|||
'short_text1' => $altResult['short_text1'],
|
||||
'price' => $altResult['price'],
|
||||
'price_unit' => $altResult['price_unit'],
|
||||
'purchase_price' => $altPurchasePriceWithCopper,
|
||||
'datanorm_base_price' => $altPurchasePrice, // Without copper
|
||||
'copper_surcharge' => $productCopperSurcharge,
|
||||
'effective_price_unit' => $priceUnit, // Actual divisor used
|
||||
'purchase_price' => $altPurchasePrice, // Calculated unit price (Datanorm + Copper)
|
||||
'datanorm_base_price' => $materialPrice / $priceUnit, // Material only per unit
|
||||
'metal_surcharge' => $metalSurcharge / $priceUnit, // Copper surcharge per unit (from Dolibarr)
|
||||
'ean' => $altResult['ean'],
|
||||
'manufacturer_ref' => $altResult['manufacturer_ref'],
|
||||
'is_invoice_supplier' => ($altResult['fk_soc'] == $import->fk_soc),
|
||||
|
|
@ -2590,18 +2599,20 @@ if ($action == 'edit' && $import->id > 0) {
|
|||
// Fehlende Lieferantenpreise aus anderen Katalogen sammeln (Anzeige weiter unten)
|
||||
if ($import->fk_soc > 0 && getDolGlobalString('IMPORTZUGFERD_DATANORM_SEARCH_ALL')) {
|
||||
// Alle vorhandenen Lieferantenpreise fuer dieses Produkt laden
|
||||
$sqlExistingPrices = "SELECT fk_soc, price, unitprice, barcode FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
|
||||
$sqlExistingPrices = "SELECT fk_soc, price, unitprice, quantity, barcode FROM ".MAIN_DB_PREFIX."product_fournisseur_price";
|
||||
$sqlExistingPrices .= " WHERE fk_product = ".(int)$line->fk_product;
|
||||
$resExistingPrices = $db->query($sqlExistingPrices);
|
||||
$existingSupplierIds = array();
|
||||
$currentSupplierPrice = 0;
|
||||
$currentSupplierQty = 1;
|
||||
$supplierEan = '';
|
||||
if ($resExistingPrices) {
|
||||
while ($objPrice = $db->fetch_object($resExistingPrices)) {
|
||||
$existingSupplierIds[$objPrice->fk_soc] = true;
|
||||
// Stueckpreis und EAN vom Rechnungslieferanten merken
|
||||
// Stueckpreis, Mindestmenge und EAN vom Rechnungslieferanten merken
|
||||
if ($objPrice->fk_soc == $import->fk_soc) {
|
||||
$currentSupplierPrice = $objPrice->unitprice;
|
||||
$currentSupplierQty = max(1, $objPrice->quantity);
|
||||
if (!empty($objPrice->barcode)) {
|
||||
$supplierEan = $objPrice->barcode;
|
||||
}
|
||||
|
|
@ -2613,10 +2624,12 @@ if ($action == 'edit' && $import->id > 0) {
|
|||
$datanormSearch = new Datanorm($db);
|
||||
$allCatalogResults = array();
|
||||
|
||||
// Load copper surcharge from product extrafields for price comparison
|
||||
// Load copper surcharge from current supplier price extrafields for price comparison
|
||||
$productCopperSurcharge = 0;
|
||||
$sqlCopper = "SELECT kupferzuschlag FROM ".MAIN_DB_PREFIX."product_extrafields";
|
||||
$sqlCopper .= " WHERE fk_object = ".(int)$line->fk_product;
|
||||
$sqlCopper = "SELECT pfe.kupferzuschlag FROM ".MAIN_DB_PREFIX."product_fournisseur_price pf";
|
||||
$sqlCopper .= " LEFT JOIN ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields pfe ON pfe.fk_object = pf.rowid";
|
||||
$sqlCopper .= " WHERE pf.fk_product = ".(int)$line->fk_product;
|
||||
$sqlCopper .= " AND pf.fk_soc = ".(int)$import->fk_soc;
|
||||
$resCopper = $db->query($sqlCopper);
|
||||
if ($resCopper && $db->num_rows($resCopper) > 0) {
|
||||
$objCopper = $db->fetch_object($resCopper);
|
||||
|
|
@ -2638,15 +2651,19 @@ 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'];
|
||||
}
|
||||
// Calculate unit price from Datanorm (same logic as supplier_alternatives)
|
||||
$priceUnit = ($catalogResult['price_unit'] > 0) ? $catalogResult['price_unit'] : 1;
|
||||
$materialPrice = $catalogResult['price'];
|
||||
|
||||
// Add copper surcharge from existing product for comparison
|
||||
// Datanorm has only material price, not copper surcharge
|
||||
$altPurchasePriceWithCopper = $altPurchasePrice + $productCopperSurcharge;
|
||||
// Datanorm has NO metal surcharge - use copper surcharge from Dolibarr supplier price
|
||||
// $productCopperSurcharge is already loaded from extrafields above
|
||||
$metalSurcharge = $productCopperSurcharge;
|
||||
|
||||
// Total price for price unit
|
||||
$totalPriceForUnit = $materialPrice + $metalSurcharge;
|
||||
|
||||
// Unit price (price per 1 piece/meter)
|
||||
$altPurchasePrice = $totalPriceForUnit / $priceUnit;
|
||||
|
||||
$missingSuppliers[] = array(
|
||||
'datanorm_id' => $catalogResult['id'],
|
||||
|
|
@ -2655,9 +2672,10 @@ if ($action == 'edit' && $import->id > 0) {
|
|||
'article_number' => $catalogResult['article_number'],
|
||||
'price' => $catalogResult['price'],
|
||||
'price_unit' => $catalogResult['price_unit'],
|
||||
'purchase_price' => $altPurchasePriceWithCopper,
|
||||
'datanorm_base_price' => $altPurchasePrice, // Without copper
|
||||
'copper_surcharge' => $productCopperSurcharge,
|
||||
'effective_price_unit' => $priceUnit,
|
||||
'purchase_price' => $altPurchasePrice, // Calculated unit price (Datanorm + Copper)
|
||||
'datanorm_base_price' => $materialPrice / $priceUnit, // Material only per unit
|
||||
'metal_surcharge' => $metalSurcharge / $priceUnit, // Copper surcharge per unit (from Dolibarr)
|
||||
'ean' => $catalogResult['ean'],
|
||||
);
|
||||
}
|
||||
|
|
@ -2680,8 +2698,13 @@ if ($action == 'edit' && $import->id > 0) {
|
|||
print '<div id="'.$toggleId.'" class="missing-suppliers-content" style="margin-top: 5px;">';
|
||||
|
||||
foreach ($missingSuppliers as $missing) {
|
||||
// Calculate price for minimum quantity
|
||||
$priceUnit = !empty($missing['effective_price_unit']) ? $missing['effective_price_unit'] : $missing['price_unit'];
|
||||
$totalPriceForUnit = $missing['price'] + (!empty($missing['metal_surcharge']) ? ($missing['metal_surcharge'] * $priceUnit) : 0);
|
||||
|
||||
$priceDiffHtml = '';
|
||||
if ($currentSupplierPrice > 0) {
|
||||
// Compare unit prices (Stückpreise)
|
||||
$pDiff = $missing['purchase_price'] - $currentSupplierPrice;
|
||||
$pDiffPercent = ($pDiff / $currentSupplierPrice) * 100;
|
||||
if ($pDiff < 0) {
|
||||
|
|
@ -2700,8 +2723,24 @@ if ($action == 'edit' && $import->id > 0) {
|
|||
print '<input type="checkbox" name="add_prices[]" value="'.dol_escape_htmltag($cbValue).'" checked class="cb-missing-price" form="missing_prices_form" style="margin-right: 5px;">';
|
||||
print '<strong>'.dol_escape_htmltag($missing['supplier_name']).'</strong>';
|
||||
print ' <code style="font-size: 0.9em;">'.dol_escape_htmltag($missing['article_number']).'</code>';
|
||||
print ' @ <strong>'.price($missing['purchase_price']).'</strong>';
|
||||
print ' @ <strong>'.price($totalPriceForUnit);
|
||||
if ($priceUnit > 1) {
|
||||
print '/'.$priceUnit;
|
||||
}
|
||||
print '</strong>';
|
||||
if ($priceUnit > 1) {
|
||||
print ' <span class="small opacitymedium">('.price($missing['purchase_price']).'/Stk.)</span>';
|
||||
}
|
||||
print $priceDiffHtml;
|
||||
// Show current Dolibarr price for comparison
|
||||
if ($currentSupplierPrice > 0) {
|
||||
$currentTotalPrice = $currentSupplierPrice * $currentSupplierQty;
|
||||
print ' <span class="small opacitymedium">| Aktuell: '.price($currentTotalPrice);
|
||||
if ($currentSupplierQty > 1) {
|
||||
print '/'.$currentSupplierQty;
|
||||
}
|
||||
print '</span>';
|
||||
}
|
||||
print '</label>';
|
||||
print '</div>';
|
||||
}
|
||||
|
|
@ -3104,14 +3143,27 @@ if ($action == 'edit' && $import->id > 0) {
|
|||
|
||||
// Price
|
||||
print '<td class="right nowraponall">';
|
||||
if ($alt['price_unit'] > 1) {
|
||||
print '<span class="small" style="color: #666;">'.price($alt['price']).'/'.$alt['price_unit'].'</span><br>';
|
||||
// Main price: Total price for minimum quantity (price_unit)
|
||||
$priceUnit = !empty($alt['effective_price_unit']) ? $alt['effective_price_unit'] : $alt['price_unit'];
|
||||
$totalPriceForUnit = $alt['price'] + (!empty($alt['metal_surcharge']) ? ($alt['metal_surcharge'] * $priceUnit) : 0);
|
||||
|
||||
// Show breakdown if copper surcharge exists
|
||||
if (!empty($alt['metal_surcharge']) && $alt['metal_surcharge'] > 0) {
|
||||
$materialPriceForUnit = $alt['price'];
|
||||
$copperForUnit = $alt['metal_surcharge'] * $priceUnit;
|
||||
print '<span class="small" style="color: #666;">'.price($materialPriceForUnit).' + '.price($copperForUnit).' Kupfer</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>';
|
||||
|
||||
// Show main price for minimum quantity
|
||||
print '<strong>'.price($totalPriceForUnit).'</strong>';
|
||||
if ($priceUnit > 1) {
|
||||
print '<span class="small" style="color: #666;">/'.$priceUnit.'</span>';
|
||||
}
|
||||
|
||||
// Show unit price as secondary info
|
||||
if ($priceUnit > 1) {
|
||||
print '<br><span class="small opacitymedium">'.price($alt['purchase_price']).'/Stk.</span>';
|
||||
}
|
||||
print '<strong>'.price($alt['purchase_price']).'</strong>';
|
||||
print '</td>';
|
||||
|
||||
// Difference from invoice supplier price
|
||||
|
|
|
|||
Loading…
Reference in a new issue