From 680fa14e8cc1aeeaf7d145c094adba6cb00a434b Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 31 May 2024 18:23:32 +0200 Subject: [PATCH] Debug v20 --- htdocs/core/modules/modStock.class.php | 50 +++++++++++++++++++ htdocs/langs/en_US/stocks.lang | 2 + htdocs/product/stock/stockatdate.php | 66 ++++++++++++++++---------- 3 files changed, 92 insertions(+), 26 deletions(-) diff --git a/htdocs/core/modules/modStock.class.php b/htdocs/core/modules/modStock.class.php index 67c0fa4b1ed..ad391a1ec92 100644 --- a/htdocs/core/modules/modStock.class.php +++ b/htdocs/core/modules/modStock.class.php @@ -395,6 +395,56 @@ class modStock extends DolibarrModules $this->export_sql_end[$r] .= ' WHERE p.rowid = sm.fk_product AND sm.fk_entrepot = e.rowid'; $this->export_sql_end[$r] .= ' AND e.entity IN ('.getEntity('stock').')'; + // Export inventory + /* + $r++; + $this->export_code[$r] = $this->rights_class.'_movement'; + $this->export_label[$r] = "Inventories"; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r] = "movement"; + $this->export_permission[$r] = array(array("stock", "lire")); + $this->export_fields_array[$r] = array( + 'i.rowid' => 'InventoryId', 'i.ref' => 'Inventoryref', 'i.date_inventory' => 'DateInventory', + 'id.rowid' => 'InventoryLineId', 'id.qty_view' => 'QtyViewed', 'id.qty_stock' => 'QtyStock', 'id.qty_regulated' => 'QtyRegulated', + 'id.batch' => 'Lotserial', + 'e.rowid' => 'IdWarehouse', 'e.ref' => 'LocationSummary', 'e.description' => 'DescWareHouse', 'e.lieu' => 'LieuWareHouse', 'e.address' => 'Address', 'e.zip' => 'Zip', 'e.town' => 'Town', + 'p.rowid' => "ProductId", 'p.ref' => "Ref", 'p.fk_product_type' => "Type", 'p.label' => "Label", 'p.description' => "Description", 'p.note' => "Note", + 'p.price' => "Price", 'p.tva_tx' => 'VAT', 'p.tosell' => "OnSell", 'p.tobuy' => 'OnBuy', 'p.duration' => "Duration", 'p.datec' => 'DateCreation', 'p.tms' => 'DateModification' + ); + if (isModEnabled('barcode')) { + $this->export_fields_array[$r] = array_merge($this->export_fields_array[$r], array('p.barcode' => 'BarCode')); + } + $this->export_TypeFields_array[$r] = array( + 'id.rowid' => 'Numeric', 'sm.value' => 'Numeric', 'sm.datem' => 'Date', 'sm.batch' => 'Text', 'sm.label' => 'Text', 'sm.inventorycode' => 'Text', + 'e.rowid' => 'List:entrepot:ref::stock', 'e.ref' => 'Text', 'e.description' => 'Text', 'e.lieu' => 'Text', 'e.address' => 'Text', 'e.zip' => 'Text', 'e.town' => 'Text', + 'p.rowid' => "Numeric", 'p.ref' => "Text", 'p.fk_product_type' => "Text", 'p.label' => "Text", 'p.description' => "Text", 'p.note' => "Text", + 'p.price' => "Numeric", 'p.tva_tx' => 'Numeric', 'p.tosell' => "Boolean", 'p.tobuy' => "Boolean", 'p.duration' => "Duree", 'p.datec' => 'Date', 'p.tms' => 'Date' + ); + if (isModEnabled('barcode')) { + $this->export_TypeFields_array[$r] = array_merge($this->export_TypeFields_array[$r], array('p.barcode' => 'Text')); + } + $this->export_entities_array[$r] = array( + 'e.rowid' => 'warehouse', 'e.ref' => 'warehouse', 'e.description' => 'warehouse', 'e.lieu' => 'warehouse', 'e.address' => 'warehouse', 'e.zip' => 'warehouse', 'e.town' => 'warehouse', + 'p.rowid' => "product", 'p.ref' => "product", 'p.fk_product_type' => "product", 'p.label' => "product", 'p.description' => "product", 'p.note' => "product", + 'p.price' => "product", 'p.tva_tx' => 'product', 'p.tosell' => "product", 'p.tobuy' => "product", 'p.duration' => "product", 'p.datec' => 'product', 'p.tms' => 'product' + ); // We define here only fields that use another icon that the one defined into export_icon + if (isModEnabled('productbatch')) { + $this->export_fields_array[$r]['sm.batch'] = 'Batch'; + $this->export_TypeFields_array[$r]['sm.batch'] = 'Text'; + $this->export_entities_array[$r]['sm.batch'] = 'movement'; + } + if (isModEnabled('barcode')) { + $this->export_entities_array[$r] = array_merge($this->export_entities_array[$r], array('p.barcode' => 'product')); + } + $this->export_aggregate_array[$r] = array('sm.value' => 'SUM'); // TODO Not used yet + $this->export_dependencies_array[$r] = array('movement' => array('sm.rowid')); // We must keep this until the aggregate_array is used. To add unique key if we ask a field of a child to avoid the DISTINCT to discard them. + + $this->export_sql_start[$r] = 'SELECT DISTINCT '; + $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'product as p, '.MAIN_DB_PREFIX.'inventory as i, '.MAIN_DB_PREFIX.'inventorydet as id, '.MAIN_DB_PREFIX.'entrepot as e'; + $this->export_sql_end[$r] .= ' WHERE p.rowid = id.fk_product AND id.fk_inventory = i.rowid AND id.fk_entrepot = e.rowid'; + $this->export_sql_end[$r] .= ' AND e.entity IN ('.getEntity('stock').')'; + */ + + // Imports //-------- diff --git a/htdocs/langs/en_US/stocks.lang b/htdocs/langs/en_US/stocks.lang index 10e476478e4..e11a0704601 100644 --- a/htdocs/langs/en_US/stocks.lang +++ b/htdocs/langs/en_US/stocks.lang @@ -101,6 +101,8 @@ VirtualStockAtDate=Virtual stock at a future date VirtualStockAtDateDesc=Virtual stock once all the pending orders that are planned to be processed before the chosen date will be finished VirtualStockDesc=Virtual stock is the stock that will remain after all open/pending actions (that affect stocks) have been performed (purchase orders received, sales orders shipped, manufacturing orders produced, etc) AtDate=At date +QtyAtDate=Quantity in stock at date +MovementsSinceDate=Movements since the date IdWarehouse=Id warehouse DescWareHouse=Description warehouse LieuWareHouse=Localisation warehouse diff --git a/htdocs/product/stock/stockatdate.php b/htdocs/product/stock/stockatdate.php index 1cc98b56487..a7293c57f6e 100644 --- a/htdocs/product/stock/stockatdate.php +++ b/htdocs/product/stock/stockatdate.php @@ -366,11 +366,12 @@ if ($mode == 'future') { // TODO Move this action into a separated files: We should not mix output with MIME type HTML and MIME type CSV in the same file. if ($ext == 'csv') { - header("Content-Type: text/csv"); + top_httphead("text/csv"); + //header("Content-Type: text/csv"); header("Content-Disposition: attachment; filename=stock".($date?'-'.date("Y-m-d", $date):'').".csv"); // Lines of title - print implode("\t", ($mode == 'future')? + print implode(";", ($mode == 'future') ? array('"Product Reference"', '"Label"', '"Current Stock"', '"'.$stocklabel.'"', '"Virtual Stock"'): array('"Product Reference"', '"Label"', '"'.$stocklabel.'"', '"Estimated Stock Value"', '"Estimate Sell Value"', '"Movements"', '"Current Stock"'))."\r\n"; } else { @@ -467,15 +468,20 @@ if ($ext == 'csv') { print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table if ($num) { - print "

'; + print 'Download CSV

"; + '" title="Download CSV" />'; + print img_picto('', 'download', 'class="pictofixedwidth"'); + print 'Download CSV'; + print ''; + print '

'; } print ''; @@ -526,9 +532,12 @@ if ($ext == 'csv') { print_liste_field_titre('VirtualStock', $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ', 'VirtualStockDesc'); } else { print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right '); - print_liste_field_titre("EstimatedStockValue", $_SERVER["PHP_SELF"], "estimatedvalue", '', $param, '', $sortfield, $sortorder, 'right ', $langs->trans("AtDate"), 1); - print_liste_field_titre("EstimatedStockValueSell", $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right ', $langs->trans("AtDate"), 1); - print_liste_field_titre('', $_SERVER["PHP_SELF"]); + $tooltiptext = $langs->trans("QtyAtDate").' x '.$langs->trans("AverageUnitPricePMPShort"); + print_liste_field_titre("EstimatedStockValue", $_SERVER["PHP_SELF"], "estimatedvalue", '', $param, '', $sortfield, $sortorder, 'right ', $tooltiptext, 1); + $tooltiptext = $langs->trans("QtyAtDate").' x '.$langs->trans("SellingPrice"); + print_liste_field_titre("EstimatedStockValueSell", $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right ', $tooltiptext, 1); + $tooltiptext = $langs->trans("MovementsSinceDate"); + print_liste_field_titre('', $_SERVER["PHP_SELF"], '', '', $param, '', '', '', 'center ', $tooltiptext, 1); print_liste_field_titre('CurrentStock', $_SERVER["PHP_SELF"], $fieldtosortcurrentstock, $param, '', '', $sortfield, $sortorder, 'right '); } @@ -586,7 +595,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { //} } else { //if ($productid > 0) { - $currentstock = $stock_prod[$objp->rowid]; + $currentstock = empty($stock_prod[$objp->rowid]) ? 0 : $stock_prod[$objp->rowid]; //} else { // $currentstock = $objp->stock; //} @@ -606,30 +615,30 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $nbofmovement += $movements_prod_warehouse_nb[$objp->rowid][$val]; } } else { - $stock -= $movements_prod[$objp->rowid]; - $nbofmovement += $movements_prod_nb[$objp->rowid]; + $stock -= empty($movements_prod[$objp->rowid]) ? 0 : $movements_prod[$objp->rowid]; + $nbofmovement += empty($movements_prod_nb[$objp->rowid]) ? 0 : $movements_prod_nb[$objp->rowid]; } } if ($ext == 'csv') { if ($mode == 'future') { - print implode("\t", array( + print implode(";", array( '"'.$objp->ref.'"', '"'.$objp->label.'"', - '"'.price(price2num($currentstock, 'MS')).'"', - '"'.price(price2num($stock, 'MS')).'"', - '"'.price(price2num($virtualstock, 'MS')).'"'))."\r\n"; + '"'.price2num($currentstock, 'MS').'"', + '"'.price2num($stock, 'MS').'"', + '"'.price2num($virtualstock, 'MS').'"'))."\r\n"; $totalvirtualstock += $virtualstock; } else { - print implode("\t", array( + print implode(";", array( '"'.$objp->ref.'"', '"'.$objp->label.'"', '"'.price(price2num($stock, 'MS')).'"', - price2num($stock * $objp->pmp, 'MT')?'"'.price(price2num($stock * $objp->pmp, 'MT'), 1).'"':'', - empty($conf->global->PRODUIT_MULTIPRICES)?'"'.price(price2num($stock * $objp->price, 'MT'), 1).'"':'"'.$langs->trans("Variable").'('.$langs->trans("OptionMULTIPRICESIsOn").')"', + price2num($stock * $objp->pmp, 'MT')?'"'.price2num($stock * $objp->pmp, 'MT').'"':'', + !getDolGlobalString('PRODUIT_MULTIPRICES')?'"'.price2num($stock * $objp->price, 'MT').'"':'"'.$langs->trans("Variable").'('.$langs->trans("OptionMULTIPRICESIsOn").')"', "$nbofmovement", - '"'.price(price2num($currentstock, 'MS')).'"'))."\r\n"; + '"'.price2num($currentstock, 'MS').'"'))."\r\n"; $totalbuyingprice += $stock * $objp->pmp; $totalsellingprice += $stock * $objp->price; } @@ -663,8 +672,8 @@ while ($i < ($limit ? min($num, $limit) : $num)) { print ''; // PMP value - print ''; // Selling value - print ''; + // Movements print '';
'.($stock ? price(price2num($stock, 'MS')) : ('0')).''; $estimatedvalue = $stock * $objp->pmp; + print 'trans("Currently").'): '.price(price2num($objp->pmp, 'MU'), 1)).'">'; if (price2num($estimatedvalue, 'MT')) { print ''.price(price2num($estimatedvalue, 'MT'), 1).''; } else { @@ -674,7 +683,11 @@ while ($i < ($limit ? min($num, $limit) : $num)) { print ''; + print 'trans("Currently").'): '.price(price2num($objp->price, 'MU'), 1)); + } + print '">'; if (!getDolGlobalString('PRODUIT_MULTIPRICES')) { print ''; if ($stock || (float) ($stock * $objp->price)) { @@ -688,6 +701,7 @@ while ($i < ($limit ? min($num, $limit) : $num)) { } print ''; if ($nbofmovement > 0) { print 'trans("Totalforthispage").'"', '', - $productid > 0 ? price(price2num($totalcurrentstock, 'MS')) : '', + $productid > 0 ? price2num($totalcurrentstock, 'MS') : '', '', price(price2num($totalvirtualstock, 'MS'))): array( '"'.$langs->trans("Totalforthispage").'"', '', '', - '"'.price(price2num($totalbuyingprice, 'MT')).'"', - !getDolGlobalString('PRODUIT_MULTIPRICES')?'"'.price(price2num($totalsellingprice, 'MT')).'"':'', + '"'.price2num($totalbuyingprice, 'MT').'"', + !getDolGlobalString('PRODUIT_MULTIPRICES')?'"'.price2num($totalsellingprice, 'MT').'"':'', '', - $productid > 0 ? price(price2num($totalcurrentstock, 'MS')) : '')); + $productid > 0 ? price2num($totalcurrentstock, 'MS') : '')); } else { if (empty($date) || !$dateIsValid) { print '
'.$langs->trans("EnterADateCriteria").'