'."\n";
// Select of all the sub-BOM lines
diff --git a/htdocs/product/card.php b/htdocs/product/card.php
index 1681ef45387..9137a3b7c10 100644
--- a/htdocs/product/card.php
+++ b/htdocs/product/card.php
@@ -16,7 +16,7 @@
* Copyright (C) 2016-2022 Charlene Benke
* Copyright (C) 2016 Meziane Sof
* Copyright (C) 2017 Josep Lluís Amador
- * Copyright (C) 2019-2021 Frédéric France
+ * Copyright (C) 2019-2022 Frédéric France
* Copyright (C) 2019-2020 Thibault FOUCART
* Copyright (C) 2020 Pierre Ardoin
*
@@ -1973,7 +1973,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print '
'.$langs->trans("Description").'
';
// We use dolibarr_details as type of DolEditor here, because we must not accept images as description is included into PDF and not accepted by TCPDF.
- $doleditor = new DolEditor('desc', $object->description, '', 160, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_PRODUCTDESC'), ROWS_4, '90%');
+ $doleditor = new DolEditor('desc', GETPOSTISSET('desc') ? GETPOST('desc', 'restricthtml') : $object->description, '', 160, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_PRODUCTDESC'), ROWS_4, '90%');
$doleditor->Create();
print "
";
@@ -1983,7 +1983,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
if (empty($conf->global->PRODUCT_DISABLE_PUBLIC_URL)) {
print '
';
}
diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php
index 2566ca24919..e34b270562e 100644
--- a/htdocs/product/class/api_products.class.php
+++ b/htdocs/product/class/api_products.class.php
@@ -253,7 +253,7 @@ class Products extends DolibarrApi
if (!$ids_only) {
$product_static = new Product($this->db);
if ($product_static->fetch($obj->rowid)) {
- if ($includestockdata && DolibarrApiAccess::$user->rights->stock->lire) {
+ if (!empty($includestockdata) && DolibarrApiAccess::$user->rights->stock->lire) {
$product_static->load_stock();
if (is_array($product_static->stock_warehouse)) {
@@ -1644,10 +1644,10 @@ class Products extends DolibarrApi
$combinations[$key]->attributes = $prodc2vp->fetchByFkCombination((int) $combination->id);
$combinations[$key] = $this->_cleanObjectDatas($combinations[$key]);
- if ($includestock==1 && DolibarrApiAccess::$user->rights->stock->lire) {
+ if (!empty($includestock) && DolibarrApiAccess::$user->rights->stock->lire) {
$productModel = new Product($this->db);
$productModel->fetch((int) $combination->fk_product_child);
- $productModel->load_stock();
+ $productModel->load_stock($includestock);
$combinations[$key]->stock_warehouse = $this->_cleanObjectDatas($productModel)->stock_warehouse;
}
}
@@ -2040,8 +2040,8 @@ class Products extends DolibarrApi
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
- if ($includestockdata && DolibarrApiAccess::$user->rights->stock->lire) {
- $this->product->load_stock();
+ if (!empty($includestockdata) && DolibarrApiAccess::$user->rights->stock->lire) {
+ $this->product->load_stock($includestockdata);
if (is_array($this->product->stock_warehouse)) {
foreach ($this->product->stock_warehouse as $keytmp => $valtmp) {
diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php
index 6c249e6b3bd..acdb88da9f5 100644
--- a/htdocs/product/class/product.class.php
+++ b/htdocs/product/class/product.class.php
@@ -1051,9 +1051,7 @@ class Product extends CommonObject
if ($result >= 0) {
if (empty($this->oldcopy)) {
- $org = new self($this->db);
- $org->fetch($this->id);
- $this->oldcopy = $org;
+ $this->oldcopy = dol_clone($this);
}
// Test if batch management is activated on existing product
@@ -1929,7 +1927,7 @@ class Product extends CommonObject
global $conf;
$result = 0;
- // We do a first seach with a select by searching with couple prodfournprice and qty only (later we will search on triplet qty/product_id/fourn_ref)
+ // We do a first search with a select by searching with couple prodfournprice and qty only (later we will search on triplet qty/product_id/fourn_ref)
$sql = "SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent,";
$sql .= " pfp.fk_product, pfp.ref_fourn, pfp.desc_fourn, pfp.fk_soc, pfp.tva_tx, pfp.fk_supplier_price_expression,";
$sql .= " pfp.default_vat_code,";
@@ -3038,12 +3036,13 @@ class Product extends CommonObject
/**
* Charge tableau des stats commande fournisseur pour le produit/service
*
- * @param int $socid Id societe pour filtrer sur une societe
- * @param string $filtrestatut Id des statuts pour filtrer sur des statuts
- * @param int $forVirtualStock Ignore rights filter for virtual stock calculation.
- * @return int Array of stats in $this->stats_commande_fournisseur, <0 if ko or >0 if ok
+ * @param int $socid Id societe pour filtrer sur une societe
+ * @param string $filtrestatut Id des statuts pour filtrer sur des statuts
+ * @param int $forVirtualStock Ignore rights filter for virtual stock calculation.
+ * @param int $dateofvirtualstock Date of virtual stock
+ * @return int Array of stats in $this->stats_commande_fournisseur, <0 if ko or >0 if ok
*/
- public function load_stats_commande_fournisseur($socid = 0, $filtrestatut = '', $forVirtualStock = 0)
+ public function load_stats_commande_fournisseur($socid = 0, $filtrestatut = '', $forVirtualStock = 0, $dateofvirtualstock = null)
{
// phpcs:enable
global $conf, $user, $hookmanager, $action;
@@ -3069,6 +3068,9 @@ class Product extends CommonObject
if ($filtrestatut != '') {
$sql .= " AND c.fk_statut in (".$this->db->sanitize($filtrestatut).")"; // Peut valoir 0
}
+ if (!empty($dateofvirtualstock)) {
+ $sql .= " AND c.date_livraison <= '".$this->db->idate($dateofvirtualstock)."'";
+ }
$result = $this->db->query($sql);
if ($result) {
@@ -3181,12 +3183,13 @@ class Product extends CommonObject
/**
* Charge tableau des stats réception fournisseur pour le produit/service
*
- * @param int $socid Id societe pour filtrer sur une societe
- * @param string $filtrestatut Id statut pour filtrer sur un statut
- * @param int $forVirtualStock Ignore rights filter for virtual stock calculation.
+ * @param int $socid Id societe pour filtrer sur une societe
+ * @param string $filtrestatut Id statut pour filtrer sur un statut
+ * @param int $forVirtualStock Ignore rights filter for virtual stock calculation.
+ * @param int $dateofvirtualstock Date of virtual stock
* @return int Array of stats in $this->stats_reception, <0 if ko or >0 if ok
*/
- public function load_stats_reception($socid = 0, $filtrestatut = '', $forVirtualStock = 0)
+ public function load_stats_reception($socid = 0, $filtrestatut = '', $forVirtualStock = 0, $dateofvirtualstock = null)
{
// phpcs:enable
global $conf, $user, $hookmanager, $action;
@@ -3212,6 +3215,9 @@ class Product extends CommonObject
if ($filtrestatut <> '') {
$sql .= " AND cf.fk_statut IN (".$this->db->sanitize($filtrestatut).")";
}
+ if (!empty($dateofvirtualstock)) {
+ $sql .= " AND fd.datec <= '".$this->db->idate($dateofvirtualstock)."'";
+ }
$result = $this->db->query($sql);
if ($result) {
@@ -3238,12 +3244,13 @@ class Product extends CommonObject
/**
* Charge tableau des stats production pour le produit/service
*
- * @param int $socid Id societe pour filtrer sur une societe
- * @param string $filtrestatut Id statut pour filtrer sur un statut
- * @param int $forVirtualStock Ignore rights filter for virtual stock calculation.
+ * @param int $socid Id societe pour filtrer sur une societe
+ * @param string $filtrestatut Id statut pour filtrer sur un statut
+ * @param int $forVirtualStock Ignore rights filter for virtual stock calculation.
+ * @param int $dateofvirtualstock Date of virtual stock
* @return integer Array of stats in $this->stats_mrptoproduce (nb=nb of order, qty=qty ordered), <0 if ko or >0 if ok
*/
- public function load_stats_inproduction($socid = 0, $filtrestatut = '', $forVirtualStock = 0)
+ public function load_stats_inproduction($socid = 0, $filtrestatut = '', $forVirtualStock = 0, $dateofvirtualstock = null)
{
// phpcs:enable
global $conf, $user, $hookmanager, $action;
@@ -3268,6 +3275,9 @@ class Product extends CommonObject
if ($filtrestatut <> '') {
$sql .= " AND m.status IN (".$this->db->sanitize($filtrestatut).")";
}
+ if (!empty($dateofvirtualstock)) {
+ $sql .= " AND m.date_valid <= '".$this->db->idate($dateofvirtualstock)."'"; // better date to code ? end of production ?
+ }
$sql .= " GROUP BY role";
$this->stats_mrptoconsume['customers'] = 0;
@@ -5037,7 +5047,7 @@ class Product extends CommonObject
$result .= (img_object(($notooltip ? '' : $label), 'service', ($notooltip ? 'class="paddingright"' : 'class="paddingright classfortooltip"'), 0, 0, $notooltip ? 0 : 1));
}
}
- $result .= $newref;
+ $result .= dol_escape_htmltag($newref);
$result .= $linkend;
if ($withpicto != 2) {
$result .= (($add_label && $this->label) ? $sep.dol_trunc($this->label, ($add_label > 1 ? $add_label : 0)) : '');
@@ -5346,10 +5356,11 @@ class Product extends CommonObject
* @param string $option '' = Load all stock info, also from closed and internal warehouses, 'nobatch', 'novirtual'
* You can also filter on 'warehouseclosed', 'warehouseopen', 'warehouseinternal'
* @param int $includedraftpoforvirtual Include draft status of PO for virtual stock calculation
+ * @param int $dateofvirtualstock Date of virtual stock
* @return int < 0 if KO, > 0 if OK
* @see load_virtual_stock(), loadBatchInfo()
*/
- public function load_stock($option = '', $includedraftpoforvirtual = null)
+ public function load_stock($option = '', $includedraftpoforvirtual = null, $dateofvirtualstock = null)
{
// phpcs:enable
global $conf;
@@ -5407,7 +5418,7 @@ class Product extends CommonObject
$this->db->free($result);
if (!preg_match('/novirtual/', $option)) {
- $this->load_virtual_stock($includedraftpoforvirtual); // This also load all arrays stats_xxx...
+ $this->load_virtual_stock($includedraftpoforvirtual, $dateofvirtualstock); // This also load all arrays stats_xxx...
}
return 1;
@@ -5424,10 +5435,11 @@ class Product extends CommonObject
* This function need a lot of load. If you use it on list, use a cache to execute it one for each product id.
*
* @param int $includedraftpoforvirtual Include draft status and not yet approved Purchase Orders for virtual stock calculation
+ * @param int $dateofvirtualstock Date of virtual stock
* @return int < 0 if KO, > 0 if OK
* @see load_stock(), loadBatchInfo()
*/
- public function load_virtual_stock($includedraftpoforvirtual = null)
+ public function load_virtual_stock($includedraftpoforvirtual = null, $dateofvirtualstock = null)
{
// phpcs:enable
global $conf, $hookmanager, $action;
@@ -5466,7 +5478,7 @@ class Product extends CommonObject
if (isset($includedraftpoforvirtual)) {
$filterStatus = '0,1,2,'.$filterStatus; // 1,2 may have already been inside $filterStatus but it is better to have twice than missing $filterStatus does not include them
}
- $result = $this->load_stats_commande_fournisseur(0, $filterStatus, 1);
+ $result = $this->load_stats_commande_fournisseur(0, $filterStatus, 1, $dateofvirtualstock);
if ($result < 0) {
dol_print_error($this->db, $this->error);
}
@@ -5478,7 +5490,7 @@ class Product extends CommonObject
if (isset($includedraftpoforvirtual)) {
$filterStatus = '0,'.$filterStatus;
}
- $result = $this->load_stats_reception(0, $filterStatus, 1);
+ $result = $this->load_stats_reception(0, $filterStatus, 1, $dateofvirtualstock);
if ($result < 0) {
dol_print_error($this->db, $this->error);
}
@@ -5490,14 +5502,14 @@ class Product extends CommonObject
if (isset($includedraftpoforvirtual)) {
$filterStatus = '0,'.$filterStatus;
}
- $result = $this->load_stats_reception(0, $filterStatus, 1); // Use same tables than when module reception is not used.
+ $result = $this->load_stats_reception(0, $filterStatus, 1, $dateofvirtualstock); // Use same tables than when module reception is not used.
if ($result < 0) {
dol_print_error($this->db, $this->error);
}
$stock_reception_fournisseur = $this->stats_reception['qty'];
}
if (!empty($conf->mrp->enabled)) {
- $result = $this->load_stats_inproduction(0, '1,2', 1);
+ $result = $this->load_stats_inproduction(0, '1,2', 1, $dateofvirtualstock);
if ($result < 0) {
dol_print_error($this->db, $this->error);
}
@@ -6196,8 +6208,6 @@ class Product extends CommonObject
}
}
-
-
/**
* Class to manage products or services.
* Do not use 'Service' as class name since it is already used by APIs.
diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php
index 49242eb47e4..9dfc90b86a4 100644
--- a/htdocs/product/fournisseurs.php
+++ b/htdocs/product/fournisseurs.php
@@ -464,6 +464,9 @@ if ($id > 0 || $ref) {
if (($action == 'add_price' || $action == 'update_price') && $usercancreate) {
$langs->load("suppliers");
+ print "\n";
+ print ' ';
+
if ($rowid) {
$object->fetch_product_fournisseur_price($rowid, 1); //Ignore the math expression when getting the price
print load_fiche_titre($langs->trans("ChangeSupplierPrice"));
@@ -480,7 +483,7 @@ if ($id > 0 || $ref) {
print '