From 17c8a32780732fab76c36e86c903291f999d83ce Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Tue, 2 Mar 2021 11:00:16 +0100 Subject: [PATCH 01/17] fix civility createion PK --- htdocs/install/mysql/tables/llx_c_civility.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/install/mysql/tables/llx_c_civility.sql b/htdocs/install/mysql/tables/llx_c_civility.sql index 1198691ed60..2084b876e7b 100644 --- a/htdocs/install/mysql/tables/llx_c_civility.sql +++ b/htdocs/install/mysql/tables/llx_c_civility.sql @@ -19,7 +19,7 @@ create table llx_c_civility ( - rowid integer PRIMARY KEY, + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL code varchar(6) NOT NULL, label varchar(50), active tinyint DEFAULT 1 NOT NULL, From 81f54003f6e1d01d694873ea5485f5131843fdd6 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Tue, 2 Mar 2021 22:35:47 +0100 Subject: [PATCH 02/17] set migration auto increment --- htdocs/install/mysql/migration/13.0.0-14.0.0.sql | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql index 68566139dec..6e5d038f095 100644 --- a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql +++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql @@ -197,3 +197,8 @@ ALTER TABLE llx_propal CHANGE COLUMN tva total_tva double(24,8) default 0; ALTER TABLE llx_propal CHANGE COLUMN total total_ttc double(24,8) default 0; ALTER TABLE llx_commande_fournisseur CHANGE COLUMN tva total_tva double(24,8) default 0; +--VMYSQL4.3 ALTER TABLE llx_c_civility CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; +--VPGSQL8.2 CREATE SEQUENCE llx_c_civility OWNED BY llx_c_civility.rowid; +--VPGSQL8.2 ALTER TABLE llx_c_civility ADD PRIMARY KEY (rowid); +--VPGSQL8.2 ALTER TABLE llx_c_civility ALTER COLUMN rowid SET DEFAULT nextval('llx_c_civility_rowid_seq'); +--VPGSQL8.2 SELECT setval('llx_c_civility_rowid_seq', MAX(rowid)) FROM llx_c_civility; From c68230981736518373a5a62d5b93129b9253d714 Mon Sep 17 00:00:00 2001 From: Florian HENRY Date: Wed, 3 Mar 2021 20:27:55 +0100 Subject: [PATCH 03/17] migration ok --- htdocs/install/mysql/migration/13.0.0-14.0.0.sql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql index 6e5d038f095..f05b9880bd6 100644 --- a/htdocs/install/mysql/migration/13.0.0-14.0.0.sql +++ b/htdocs/install/mysql/migration/13.0.0-14.0.0.sql @@ -198,7 +198,6 @@ ALTER TABLE llx_propal CHANGE COLUMN total total_ttc double(24,8) default 0; ALTER TABLE llx_commande_fournisseur CHANGE COLUMN tva total_tva double(24,8) default 0; --VMYSQL4.3 ALTER TABLE llx_c_civility CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; ---VPGSQL8.2 CREATE SEQUENCE llx_c_civility OWNED BY llx_c_civility.rowid; ---VPGSQL8.2 ALTER TABLE llx_c_civility ADD PRIMARY KEY (rowid); +--VPGSQL8.2 CREATE SEQUENCE llx_c_civility_rowid_seq OWNED BY llx_c_civility.rowid; --VPGSQL8.2 ALTER TABLE llx_c_civility ALTER COLUMN rowid SET DEFAULT nextval('llx_c_civility_rowid_seq'); --VPGSQL8.2 SELECT setval('llx_c_civility_rowid_seq', MAX(rowid)) FROM llx_c_civility; From 6a242edd8bc480c253d40b0c857eadcf60aa3539 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 4 Mar 2021 15:29:47 +0100 Subject: [PATCH 04/17] check unicity of serial number --- htdocs/langs/en_US/productbatch.lang | 2 + htdocs/langs/fr_FR/productbatch.lang | 2 + .../stock/class/mouvementstock.class.php | 47 ++++++++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang index 3ab83908ff5..37c34b9caed 100644 --- a/htdocs/langs/en_US/productbatch.lang +++ b/htdocs/langs/en_US/productbatch.lang @@ -24,3 +24,5 @@ ProductLotSetup=Setup of module lot/serial ShowCurrentStockOfLot=Show current stock for couple product/lot ShowLogOfMovementIfLot=Show log of movements for couple product/lot StockDetailPerBatch=Stock detail per lot +SerialNumberAlreadyInUse=Serial number %s is already used for product %s + diff --git a/htdocs/langs/fr_FR/productbatch.lang b/htdocs/langs/fr_FR/productbatch.lang index 76cba909e2c..edfd928453c 100644 --- a/htdocs/langs/fr_FR/productbatch.lang +++ b/htdocs/langs/fr_FR/productbatch.lang @@ -24,3 +24,5 @@ ProductLotSetup=Configuration du module lot/série ShowCurrentStockOfLot=Afficher le stock actuel pour le couple produit / lot ShowLogOfMovementIfLot=Afficher l'historique des mouvements de couple produit / lot StockDetailPerBatch=Stock détaillé par lot +SerialNumberAlreadyInUse=Le numéro de série %s est déjà utilisé pour le produit %s + diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 17fe7193658..d7df01e882f 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -192,7 +192,7 @@ class MouvementStock extends CommonObject } } // end hook at beginning - + // Clean parameters $price = price2num($price, 'MU'); // Clean value for the casse we receive a float zero value, to have it a real zero value. if (empty($price)) $price = 0; @@ -568,6 +568,13 @@ class MouvementStock extends CommonObject // Update detail stock for batch product if (!$error && !empty($conf->productbatch->enabled) && $product->hasbatch() && !$skip_batch) { + // check unicity for serial numbered equipments ( different for lots managed products) + if ( $product->status_batch == 2 && $qty > 0 && $this->getBatchCount($fk_product, $batch) > 0 ) + { + $error++; + $this->errors[] = $langs->trans("SerialNumberAlreadyInUse", $batch, $product->ref); + } + if ($id_product_batch > 0) { $result = $this->createBatch($id_product_batch, $qty); @@ -1208,4 +1215,42 @@ class MouvementStock extends CommonObject return $this->deleteCommon($user, $notrigger); //return $this->deleteCommon($user, $notrigger, 1); } + + /** + * Retrieve number of equipments for a product batch + * + * @return int <0 if KO, number of equipments if OK + */ + private function getBatchCount($fk_product, $batch) + { + global $conf; + + $cpt = 0; + + $sql = "SELECT sum(pb.qty) as cpt"; + $sql .= " FROM ".MAIN_DB_PREFIX."product_batch as pb"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps ON ps.rowid = pb.fk_product_stock"; + $sql .= " WHERE ps.fk_product = " . $fk_product; + $sql .= " AND pb.batch = '" . $batch . "'"; + + $result = $this->db->query($sql); + if ($result) { + if ($this->db->num_rows($result)) { + + $obj = $this->db->fetch_object($result); + + $cpt = $obj->cpt; + + } + + $this->db->free($result); + } + else + { + dol_print_error($this->db); + return -1; + } + + return $cpt; + } } From faf7b1d659a600657c962f2ce4e16c13934d3d7c Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 4 Mar 2021 15:31:51 +0100 Subject: [PATCH 05/17] adapt dispatch for serial numbers --- htdocs/fourn/commande/dispatch.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index 0ee9e87db4d..78e3884e9c4 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -855,7 +855,7 @@ if ($id > 0 || !empty($ref)) { // Already dispatched print ''.$products_dispatched[$objp->rowid].''; - if (!empty($conf->productbatch->enabled) && $objp->tobatch == 1) { + if (!empty($conf->productbatch->enabled) && $objp->tobatch > 0) { $type = 'batch'; print ''; print ''; // Qty to dispatch @@ -967,7 +967,7 @@ if ($id > 0 || !empty($ref)) { print ''; print ''; - if (!empty($conf->productbatch->enabled) && $objp->tobatch == 1) { + if (!empty($conf->productbatch->enabled) && $objp->tobatch > 0) { $type = 'batch'; print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"'); } else { From a4dcf603ed24c08c49dbc67e88bd3b5db99ed94f Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 4 Mar 2021 15:33:06 +0100 Subject: [PATCH 06/17] fix repair batch stock for batch=2 --- htdocs/install/repair.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/install/repair.php b/htdocs/install/repair.php index 2a9c2bb11f2..80678abe24f 100644 --- a/htdocs/install/repair.php +++ b/htdocs/install/repair.php @@ -897,7 +897,7 @@ if ($ok && GETPOST('clean_product_stock_batch', 'alpha')) { $sql = "SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch"; $sql .= " FROM ".MAIN_DB_PREFIX."product as p, ".MAIN_DB_PREFIX."product_stock as ps LEFT JOIN ".MAIN_DB_PREFIX."product_batch as pb ON ps.rowid = pb.fk_product_stock"; $sql .= " WHERE p.rowid = ps.fk_product"; - $sql .= " AND p.tobatch = 1"; + $sql .= " AND p.tobatch > 0"; $sql .= " GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel"; $sql .= " HAVING reel != SUM(pb.qty) or SUM(pb.qty) IS NULL"; print $sql; @@ -981,7 +981,7 @@ if ($ok && GETPOST('clean_product_stock_negative_if_batch', 'alpha')) { $sql = "SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch"; $sql .= " FROM ".MAIN_DB_PREFIX."product as p, ".MAIN_DB_PREFIX."product_stock as ps, ".MAIN_DB_PREFIX."product_batch as pb"; $sql .= " WHERE p.rowid = ps.fk_product AND ps.rowid = pb.fk_product_stock"; - $sql .= " AND p.tobatch = 1"; + $sql .= " AND p.tobatch > 0"; $sql .= " GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel"; $sql .= " HAVING reel != SUM(pb.qty)"; $resql = $db->query($sql); From 53cf042a574ee5d2758a81f8dbca3319c57fd769 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 4 Mar 2021 15:35:53 +0100 Subject: [PATCH 07/17] adapt tobatch import/export --- htdocs/core/modules/modProduct.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/modules/modProduct.class.php b/htdocs/core/modules/modProduct.class.php index f972c235802..2bd42d64e11 100644 --- a/htdocs/core/modules/modProduct.class.php +++ b/htdocs/core/modules/modProduct.class.php @@ -587,7 +587,7 @@ class modProduct extends DolibarrModules )); $this->import_regex_array[$r] = array_merge($this->import_regex_array[$r], array( - 'p.tobatch' => '^[0|1]$' + 'p.tobatch' => '^[0|1|2]$' )); $this->import_convertvalue_array[$r] = array_merge($this->import_convertvalue_array[$r], array( @@ -679,7 +679,7 @@ class modProduct extends DolibarrModules //clauses copied from import_fields_array if (!empty($conf->stock->enabled)) { $import_sample = array_merge($import_sample, array( - 'p.tobatch'=>"0 (don't use) / 1 (use batch/serial number)", + 'p.tobatch'=>"0 (don't use) / 1 (use batch) / 2 (use serial number)", 'p.seuil_stock_alerte' => '', 'p.pmp' => '0', 'p.desiredstock' => '' From 83350cde8fd85ca94b69505f047d8284fd9f4e7a Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 4 Mar 2021 15:40:23 +0100 Subject: [PATCH 08/17] remove hidden constant MAIN_ADVANCE_NUMLOT --- htdocs/product/card.php | 18 +++--------------- htdocs/product/class/product.class.php | 10 +++++----- htdocs/product/list.php | 25 ++++++++----------------- 3 files changed, 16 insertions(+), 37 deletions(-) diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 3eccae1e114..d7080e39417 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -1084,11 +1084,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // Batch number management if (!empty($conf->productbatch->enabled)) { print ''.$langs->trans("ManageLotSerial").''; - if (empty($conf->global ->MAIN_ADVANCE_NUMLOT)) { - $statutarray = array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch")); - } else { - $statutarray = array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch"), '2' => $langs->trans("ProductStatusOnSerial")); - } + $statutarray = array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch"), '2' => $langs->trans("ProductStatusOnSerial")); print $form->selectarray('status_batch', $statutarray, GETPOST('status_batch')); print ''; } @@ -1548,11 +1544,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if ($conf->productbatch->enabled) { if ($object->isProduct() || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { print ''.$langs->trans("ManageLotSerial").''; - if (empty($conf->global ->MAIN_ADVANCE_NUMLOT)) { - $statutarray = array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch")); - } else { - $statutarray = array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch"), '2' => $langs->trans("ProductStatusOnSerial")); - } + $statutarray = array('0' => $langs->trans("ProductStatusNotOnBatch"), '1' => $langs->trans("ProductStatusOnBatch"), '2' => $langs->trans("ProductStatusOnSerial")); print $form->selectarray('status_batch', $statutarray, $object->status_batch); print ''; } @@ -2040,11 +2032,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { if (!empty($conf->productbatch->enabled)) { if ($object->isProduct() || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { print ''.$langs->trans("ManageLotSerial").''; - if (!empty($conf->use_javascript_ajax) && $usercancreate && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE) && empty($conf->global->MAIN_ADVANCE_NUMLOT)) { - print ajax_object_onoff($object, 'status_batch', 'tobatch', 'ProductStatusOnBatch', 'ProductStatusNotOnBatch'); - } else { - print $object->getLibStatut(0, 2); - } + print $object->getLibStatut(0, 2); print ''; } } diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 99e571fb8b7..072b113df7e 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -4747,10 +4747,10 @@ class Product extends CommonObject if ($type == 2) { switch ($mode) { case 0: - $label = ($status == 0 ? $langs->trans('ProductStatusNotOnBatch') : ($status == 1 || empty($conf->global->MAIN_ADVANCE_NUMLOT) ? $langs->trans('ProductStatusOnBatch') : $langs->trans('ProductStatusOnSerial'))); + $label = ($status == 0 ? $langs->trans('ProductStatusNotOnBatch') : ($status == 1 ? $langs->trans('ProductStatusOnBatch') : $langs->trans('ProductStatusOnSerial'))); return dolGetStatus($label); case 1: - $label = ($status == 0 ? $langs->trans('ProductStatusNotOnBatchShort') : ($status == 1 || empty($conf->global->MAIN_ADVANCE_NUMLOT) ? $langs->trans('ProductStatusOnBatchShort') : $langs->trans('ProductStatusOnSerialShort'))); + $label = ($status == 0 ? $langs->trans('ProductStatusNotOnBatchShort') : ($status == 1 ? $langs->trans('ProductStatusOnBatchShort') : $langs->trans('ProductStatusOnSerialShort'))); return dolGetStatus($label); case 2: return $this->LibStatut($status, 3, 2).' '.$this->LibStatut($status, 1, 2); @@ -4788,10 +4788,10 @@ class Product extends CommonObject $labelStatus = $langs->trans('ProductStatusOnBuyShort'); $labelStatusShort = $langs->trans('ProductStatusOnBuy'); } elseif ($type == 2) { - $labelStatus = ($status == 1 || empty($conf->global->MAIN_ADVANCE_NUMLOT) ? $langs->trans('ProductStatusOnBatch') : $langs->trans('ProductStatusOnSerial')); - $labelStatusShort = ($status == 1 || empty($conf->global->MAIN_ADVANCE_NUMLOT) ? $langs->trans('ProductStatusOnBatchShort') : $langs->trans('ProductStatusOnSerialShort')); + $labelStatus = ($status == 1 ? $langs->trans('ProductStatusOnBatch') : $langs->trans('ProductStatusOnSerial')); + $labelStatusShort = ($status == 1 ? $langs->trans('ProductStatusOnBatchShort') : $langs->trans('ProductStatusOnSerialShort')); } - } elseif (! empty($conf->global->MAIN_ADVANCE_NUMLOT) && $type == 2 && $status == 2) { + } elseif ( $type == 2 && $status == 2 ) { $labelStatus = $langs->trans('ProductStatusOnSerial'); $labelStatusShort = $langs->trans('ProductStatusOnSerialShort'); } diff --git a/htdocs/product/list.php b/htdocs/product/list.php index 1e96e7d97f8..5bc973e56b7 100644 --- a/htdocs/product/list.php +++ b/htdocs/product/list.php @@ -971,18 +971,13 @@ if ($resql) { // To batch if (!empty($arrayfields['p.tobatch']['checked'])) { print ''; - - if (empty($conf->global ->MAIN_ADVANCE_NUMLOT)) { - print $form->selectyesno('search_tobatch', $search_tobatch, 1, false, 1); - } else { - $statutarray = array( - '-1' => '', - '0' => $langs->trans("ProductStatusNotOnBatchShort"), - '1' => $langs->trans("ProductStatusOnBatchShort"), - '2' => $langs->trans("ProductStatusOnSerialShort") - ); - print $form->selectarray('search_tobatch', $statutarray, $search_tobatch); - } + $statutarray = array( + '-1' => '', + '0' => $langs->trans("ProductStatusNotOnBatchShort"), + '1' => $langs->trans("ProductStatusOnBatchShort"), + '2' => $langs->trans("ProductStatusOnSerialShort") + ); + print $form->selectarray('search_tobatch', $statutarray, $search_tobatch); print ''; } // Country @@ -1672,11 +1667,7 @@ if ($resql) { // Lot/Serial if (!empty($arrayfields['p.tobatch']['checked'])) { print ''; - if (empty($conf->global->MAIN_ADVANCE_NUMLOT)) { - print yn($obj->tobatch); - } else { - print $product_static->getLibStatut(1, 2); - } + print $product_static->getLibStatut(1, 2); print ''; if (!$i) { $totalarray['nbfield']++; From 1d2372b9ef9c91b0b2faf75ca9ca4c42014069a8 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 4 Mar 2021 17:47:43 +0100 Subject: [PATCH 09/17] fix for travis and sticker --- htdocs/product/stock/class/mouvementstock.class.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index d7df01e882f..6e0d3983f06 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -1219,7 +1219,9 @@ class MouvementStock extends CommonObject /** * Retrieve number of equipments for a product batch * - * @return int <0 if KO, number of equipments if OK + * @param int $fk_product Product id + * @param varchar $batch batch number + * @return int <0 if KO, number of equipments if OK */ private function getBatchCount($fk_product, $batch) { @@ -1231,7 +1233,7 @@ class MouvementStock extends CommonObject $sql .= " FROM ".MAIN_DB_PREFIX."product_batch as pb"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps ON ps.rowid = pb.fk_product_stock"; $sql .= " WHERE ps.fk_product = " . $fk_product; - $sql .= " AND pb.batch = '" . $batch . "'"; + $sql .= " AND pb.batch = '" . $this->db->escape($batch) . "'"; $result = $this->db->query($sql); if ($result) { @@ -1241,12 +1243,11 @@ class MouvementStock extends CommonObject $cpt = $obj->cpt; - } + } $this->db->free($result); } - else - { + else { dol_print_error($this->db); return -1; } From c4ad4a33e4e951812b3ec91e499c352ebb27b915 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 4 Mar 2021 17:49:28 +0100 Subject: [PATCH 10/17] fix for sticker --- .../stock/class/mouvementstock.class.php | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 6e0d3983f06..0bdeee6522d 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -1229,29 +1229,29 @@ class MouvementStock extends CommonObject $cpt = 0; - $sql = "SELECT sum(pb.qty) as cpt"; - $sql .= " FROM ".MAIN_DB_PREFIX."product_batch as pb"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps ON ps.rowid = pb.fk_product_stock"; - $sql .= " WHERE ps.fk_product = " . $fk_product; - $sql .= " AND pb.batch = '" . $this->db->escape($batch) . "'"; + $sql = "SELECT sum(pb.qty) as cpt"; + $sql .= " FROM ".MAIN_DB_PREFIX."product_batch as pb"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps ON ps.rowid = pb.fk_product_stock"; + $sql .= " WHERE ps.fk_product = " . $fk_product; + $sql .= " AND pb.batch = '" . $this->db->escape($batch) . "'"; - $result = $this->db->query($sql); - if ($result) { - if ($this->db->num_rows($result)) { + $result = $this->db->query($sql); + if ($result) { + if ($this->db->num_rows($result)) { - $obj = $this->db->fetch_object($result); + $obj = $this->db->fetch_object($result); - $cpt = $obj->cpt; + $cpt = $obj->cpt; - } + } - $this->db->free($result); - } - else { - dol_print_error($this->db); - return -1; - } + $this->db->free($result); + } + else { + dol_print_error($this->db); + return -1; + } - return $cpt; + return $cpt; } } From 64036706ed8117c9bce51e60fbf20c201c4e864e Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Thu, 4 Mar 2021 17:52:05 +0100 Subject: [PATCH 11/17] fix for sticker --- htdocs/product/stock/class/mouvementstock.class.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 0bdeee6522d..02e3988a477 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -1238,16 +1238,12 @@ class MouvementStock extends CommonObject $result = $this->db->query($sql); if ($result) { if ($this->db->num_rows($result)) { - $obj = $this->db->fetch_object($result); - $cpt = $obj->cpt; - } $this->db->free($result); - } - else { + } else { dol_print_error($this->db); return -1; } From 2c8808b2ccc00c369a1c7ae5d9876bafaad024a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Thu, 4 Mar 2021 20:11:30 +0100 Subject: [PATCH 12/17] Update pre-commit --- dev/examples/git/pre-commit | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dev/examples/git/pre-commit b/dev/examples/git/pre-commit index 790632dda9e..72b0ca61704 100644 --- a/dev/examples/git/pre-commit +++ b/dev/examples/git/pre-commit @@ -1,5 +1,7 @@ #!/bin/sh -# To install this precommit file: TODO +# To install this precommit file: put this file in your local repo in .git/hooks directory and make it executable +# you need to adapt the path to your phpcs install +# when running git commit, it first execute this file checking only modified files, so it is faster than running on all files # To run the fix manually: cd ~/git/dolibarr; phpcbf -s -p -d memory_limit=-1 --extensions=php --colors --tab-width=4 --standard=dev/setup/codesniffer/ruleset.xml --encoding=utf-8 --runtime-set ignore_warnings_on_exit true fileordir PROJECT=`php -r "echo dirname(dirname(dirname(realpath('$0'))));"` From b53d598567b9cd2da8b3e77b4f999b1a3dfa3008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Thu, 4 Mar 2021 20:15:37 +0100 Subject: [PATCH 13/17] Update pre-commit --- dev/examples/git/pre-commit | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev/examples/git/pre-commit b/dev/examples/git/pre-commit index 72b0ca61704..273fa9f620b 100644 --- a/dev/examples/git/pre-commit +++ b/dev/examples/git/pre-commit @@ -1,6 +1,8 @@ #!/bin/sh # To install this precommit file: put this file in your local repo in .git/hooks directory and make it executable # you need to adapt the path to your phpcs install +# if phpcs check fail, then it run phpcbf to fix automaticaly the syntax, and git commit is canceled +# if you have a multiprocessor computer, you can add to the option --parallel=xx # when running git commit, it first execute this file checking only modified files, so it is faster than running on all files # To run the fix manually: cd ~/git/dolibarr; phpcbf -s -p -d memory_limit=-1 --extensions=php --colors --tab-width=4 --standard=dev/setup/codesniffer/ruleset.xml --encoding=utf-8 --runtime-set ignore_warnings_on_exit true fileordir From 863ba52b15a90d034382cb8d909adad782c3b062 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 5 Mar 2021 07:59:55 +0100 Subject: [PATCH 14/17] add inner join and test error --- .../stock/class/mouvementstock.class.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 02e3988a477..29eb5a1269f 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -575,14 +575,17 @@ class MouvementStock extends CommonObject $this->errors[] = $langs->trans("SerialNumberAlreadyInUse", $batch, $product->ref); } - if ($id_product_batch > 0) + if ( ! $error ) { - $result = $this->createBatch($id_product_batch, $qty); - } else { - $param_batch = array('fk_product_stock' =>$fk_product_stock, 'batchnumber'=>$batch); - $result = $this->createBatch($param_batch, $qty); + if ($id_product_batch > 0) + { + $result = $this->createBatch($id_product_batch, $qty); + } else { + $param_batch = array('fk_product_stock' =>$fk_product_stock, 'batchnumber'=>$batch); + $result = $this->createBatch($param_batch, $qty); + } + if ($result < 0) $error++; } - if ($result < 0) $error++; } // Update PMP and denormalized value of stock qty at product level @@ -1231,7 +1234,7 @@ class MouvementStock extends CommonObject $sql = "SELECT sum(pb.qty) as cpt"; $sql .= " FROM ".MAIN_DB_PREFIX."product_batch as pb"; - $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps ON ps.rowid = pb.fk_product_stock"; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."product_stock as ps ON ps.rowid = pb.fk_product_stock"; $sql .= " WHERE ps.fk_product = " . $fk_product; $sql .= " AND pb.batch = '" . $this->db->escape($batch) . "'"; From acea36acf2900eda0f87ea1c287916d960fd0093 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 5 Mar 2021 08:39:30 +0100 Subject: [PATCH 15/17] better check for unicity --- htdocs/langs/en_US/productbatch.lang | 2 +- htdocs/langs/fr_FR/productbatch.lang | 2 +- .../product/stock/class/mouvementstock.class.php | 14 +++++++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/htdocs/langs/en_US/productbatch.lang b/htdocs/langs/en_US/productbatch.lang index 37c34b9caed..36adfd571fb 100644 --- a/htdocs/langs/en_US/productbatch.lang +++ b/htdocs/langs/en_US/productbatch.lang @@ -25,4 +25,4 @@ ShowCurrentStockOfLot=Show current stock for couple product/lot ShowLogOfMovementIfLot=Show log of movements for couple product/lot StockDetailPerBatch=Stock detail per lot SerialNumberAlreadyInUse=Serial number %s is already used for product %s - +TooManyQtyForSerialNumber=You can only have one product %s for serial number %S diff --git a/htdocs/langs/fr_FR/productbatch.lang b/htdocs/langs/fr_FR/productbatch.lang index edfd928453c..94ceb434bfd 100644 --- a/htdocs/langs/fr_FR/productbatch.lang +++ b/htdocs/langs/fr_FR/productbatch.lang @@ -25,4 +25,4 @@ ShowCurrentStockOfLot=Afficher le stock actuel pour le couple produit / lot ShowLogOfMovementIfLot=Afficher l'historique des mouvements de couple produit / lot StockDetailPerBatch=Stock détaillé par lot SerialNumberAlreadyInUse=Le numéro de série %s est déjà utilisé pour le produit %s - +TooManyQtyForSerialNumber=Vous ne pouvez avoir qu'un produit %s avec le numéro de série %s diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index 29eb5a1269f..b7000ebb557 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -569,10 +569,18 @@ class MouvementStock extends CommonObject if (!$error && !empty($conf->productbatch->enabled) && $product->hasbatch() && !$skip_batch) { // check unicity for serial numbered equipments ( different for lots managed products) - if ( $product->status_batch == 2 && $qty > 0 && $this->getBatchCount($fk_product, $batch) > 0 ) + if ( $product->status_batch == 2 && $qty > 0 ) { - $error++; - $this->errors[] = $langs->trans("SerialNumberAlreadyInUse", $batch, $product->ref); + if ( $this->getBatchCount($fk_product, $batch) > 0 ) + { + $error++; + $this->errors[] = $langs->trans("SerialNumberAlreadyInUse", $batch, $product->ref); + } + elseif { $qty > 1 } + { + $error++; + $this->errors[] = $langs->trans("TooManyQtyForSerialNumber", $product->ref, $batch); + } } if ( ! $error ) From acb87418492dc3884e898a96c943034b10b99909 Mon Sep 17 00:00:00 2001 From: Christophe Battarel Date: Fri, 5 Mar 2021 08:40:26 +0100 Subject: [PATCH 16/17] fix typo --- htdocs/product/stock/class/mouvementstock.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/stock/class/mouvementstock.class.php b/htdocs/product/stock/class/mouvementstock.class.php index b7000ebb557..59bc60f342b 100644 --- a/htdocs/product/stock/class/mouvementstock.class.php +++ b/htdocs/product/stock/class/mouvementstock.class.php @@ -576,7 +576,7 @@ class MouvementStock extends CommonObject $error++; $this->errors[] = $langs->trans("SerialNumberAlreadyInUse", $batch, $product->ref); } - elseif { $qty > 1 } + elseif ( $qty > 1 ) { $error++; $this->errors[] = $langs->trans("TooManyQtyForSerialNumber", $product->ref, $batch); From dd833633925ee261639f8cacf8bf8d1d51c07266 Mon Sep 17 00:00:00 2001 From: Gauthier PC portable 024 Date: Fri, 5 Mar 2021 10:12:18 +0100 Subject: [PATCH 17/17] FIX : several bugs on salaries + id salary in payments list --- htdocs/salaries/payments.php | 37 +++++++++++++++++++++++++++--------- htdocs/user/bank.php | 4 ++-- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/htdocs/salaries/payments.php b/htdocs/salaries/payments.php index f87209eee52..5c0b0c73956 100644 --- a/htdocs/salaries/payments.php +++ b/htdocs/salaries/payments.php @@ -2,6 +2,7 @@ /* Copyright (C) 2011-2019 Alexandre Spangaro * Copyright (C) 2015-2016 Laurent Destailleur * Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2021 Gauthier VERDOL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +25,7 @@ */ require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/salaries/class/salary.class.php'; require_once DOL_DOCUMENT_ROOT.'/salaries/class/paymentsalary.class.php'; require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; if (!empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; @@ -68,6 +70,7 @@ if (!$sortfield) $sortfield = "s.datep,s.rowid"; if (!$sortorder) $sortorder = "DESC,DESC"; $search_ref = GETPOST('search_ref', 'int'); +$search_ref_salary = GETPOST('search_ref_salary', 'int'); $search_user = GETPOST('search_user', 'alpha'); $search_label = GETPOST('search_label', 'alpha'); $search_date_start = dol_mktime(0, 0, 0, GETPOST('search_date_startmonth', 'int'), GETPOST('search_date_startday', 'int'), GETPOST('search_date_startyear', 'int')); @@ -131,6 +134,7 @@ if (empty($reshook)) { // Purge search criteria if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers $search_ref = ""; + $search_ref_salary = ""; $search_user = ""; $search_label = ""; $search_date_start = ''; @@ -163,7 +167,8 @@ if (empty($reshook)) { */ $form = new Form($db); -$salstatic = new PaymentSalary($db); +$salstatic = new Salary($db); +$paymentsalstatic = new PaymentSalary($db); $userstatic = new User($db); $accountstatic = new Account($db); @@ -174,22 +179,24 @@ $help_url = ''; $title = $langs->trans('SalariesPayments'); $sql = "SELECT u.rowid as uid, u.lastname, u.firstname, u.login, u.email, u.admin, u.salary as current_salary, u.fk_soc as fk_soc, u.statut as status,"; -$sql .= " s.rowid, s.fk_user, s.amount, s.salary, s.label, s.datep as datep, s.datev as datev, s.fk_typepayment as type, s.num_payment, s.fk_bank,"; +$sql .= " s.rowid, s.fk_user, s.amount, s.salary, sal.rowid as id_salary, sal.label, s.datep as datep, b.datev as datev, s.fk_typepayment as type, s.num_payment, s.fk_bank,"; $sql .= " ba.rowid as bid, ba.ref as bref, ba.number as bnumber, ba.account_number, ba.fk_accountancy_journal, ba.label as blabel,"; $sql .= " pst.code as payment_code"; $sql .= " FROM ".MAIN_DB_PREFIX."payment_salary as s"; +$sql .= " INNER JOIN ".MAIN_DB_PREFIX."salary as sal ON (sal.rowid = s.fk_salary)"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as pst ON s.fk_typepayment = pst.id"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank as b ON s.fk_bank = b.rowid"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."bank_account as ba ON b.fk_account = ba.rowid,"; $sql .= " ".MAIN_DB_PREFIX."user as u"; -$sql .= " WHERE u.rowid = s.fk_user"; +$sql .= " WHERE u.rowid = sal.fk_user"; $sql .= " AND s.entity IN (".getEntity('payment_salaries').")"; if (empty($user->rights->salaries->readall)) $sql .= " AND s.fk_user IN (".join(',', $childids).")"; // Search criteria if ($search_ref) $sql .= " AND s.rowid=".((int) $search_ref); +if ($search_ref_salary) $sql .= " AND sal.rowid=".((int) $search_ref_salary); if ($search_user) $sql .= natural_search(array('u.login', 'u.lastname', 'u.firstname', 'u.email'), $search_user); -if ($search_label) $sql .= natural_search(array('s.label'), $search_label); +if ($search_label) $sql .= natural_search(array('sal.label'), $search_label); if ($search_date_start) $sql .= " AND s.datep >= '".$db->idate($search_date_start)."'"; if ($search_date_end) $sql .= " AND s.datep <= '".$db->idate($search_date_end)."'"; if ($search_amount) $sql .= natural_search("s.amount", $search_amount, 1); @@ -241,6 +248,7 @@ if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.urlencode($l if ($search_type_id) $param .= '&search_type_id='.urlencode($search_type_id); if ($optioncss != '') $param .= '&optioncss='.urlencode($optioncss); if ($search_ref) $param .= '&search_ref='.urlencode($search_ref); +if ($search_ref_salary) $param .= '&search_ref_salary='.urlencode($search_ref_salary); if ($search_user > 0) $param .= '&search_user='.urlencode($search_user); if ($search_label) $param .= '&search_label='.urlencode($search_label); if ($search_account) $param .= '&search_account='.urlencode($search_account); @@ -292,6 +300,10 @@ print ''; print ''; print ''; print ''; +// Salary +print ''; +print ''; +print ''; // Label print ''; // Date payment @@ -339,10 +351,11 @@ print ''."\n"; print ''; print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "s.rowid", "", $param, "", $sortfield, $sortorder); print_liste_field_titre("Employee", $_SERVER["PHP_SELF"], "u.rowid", "", $param, "", $sortfield, $sortorder); +print_liste_field_titre("Salary", $_SERVER["PHP_SELF"], "sal.rowid", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Label", $_SERVER["PHP_SELF"], "s.label", "", $param, 'class="left"', $sortfield, $sortorder); print_liste_field_titre("DatePayment", $_SERVER["PHP_SELF"], "s.datep,s.rowid", "", $param, '', $sortfield, $sortorder, 'center '); -print_liste_field_titre("DateValue", $_SERVER["PHP_SELF"], "s.datev,s.rowid", "", $param, '', $sortfield, $sortorder, 'center '); -print_liste_field_titre("PaymentMode", $_SERVER["PHP_SELF"], "type", "", $param, 'class="left"', $sortfield, $sortorder); +print_liste_field_titre("DateValue", $_SERVER["PHP_SELF"], "b.datev,s.rowid", "", $param, '', $sortfield, $sortorder, 'center '); +print_liste_field_titre("PaymentMode", $_SERVER["PHP_SELF"], "pst.code", "", $param, 'class="left"', $sortfield, $sortorder); if (!empty($conf->banque->enabled)) print_liste_field_titre("BankAccount", $_SERVER["PHP_SELF"], "ba.label", "", $param, "", $sortfield, $sortorder); print_liste_field_titre("PayedByThisPayment", $_SERVER["PHP_SELF"], "s.amount", "", $param, 'class="right"', $sortfield, $sortorder); // Extra fields @@ -388,17 +401,23 @@ while ($i < ($limit ? min($num, $limit) : $num)) { $userstatic->socid = $obj->fk_soc; $userstatic->statut = $obj->status; - $salstatic->id = $obj->rowid; - $salstatic->ref = $obj->rowid; + $salstatic->id = $obj->id_salary; + $salstatic->ref = $obj->id_salary; + + $paymentsalstatic->id = $obj->rowid; + $paymentsalstatic->ref = $obj->rowid; // Ref - print "".$salstatic->getNomUrl(1)."\n"; + print "".$paymentsalstatic->getNomUrl(1)."\n"; if (!$i) $totalarray['nbfield']++; // Employee print "".$userstatic->getNomUrl(1)."\n"; if (!$i) $totalarray['nbfield']++; + print "".$salstatic->getNomUrl(1)."\n"; + if (!$i) $totalarray['nbfield']++; + // Label payment print "".dol_trunc($obj->label, 40)."\n"; if (!$i) $totalarray['nbfield']++; diff --git a/htdocs/user/bank.php b/htdocs/user/bank.php index 39d5266ec57..df5757992f0 100644 --- a/htdocs/user/bank.php +++ b/htdocs/user/bank.php @@ -356,7 +356,7 @@ if ($action != 'edit' && $action != 'create') { // If not bank account yet, $ac if (!empty($conf->salaries->enabled) && $user->rights->salaries->read && (in_array($object->id, $childids) || $object->id == $user->id) ) { - $salary = new PaymentSalary($db); + $payment_salary = new PaymentSalary($db); $sql = "SELECT ps.rowid, s.datesp, s.dateep, ps.amount"; $sql .= " FROM ".MAIN_DB_PREFIX."payment_salary as ps"; @@ -372,7 +372,7 @@ if ($action != 'edit' && $action != 'create') { // If not bank account yet, $ac print ''; print ''; - print '
'; + print ''; print '';
'.$langs->trans("LastSalaries", ($num <= $MAXLIST ? "" : $MAXLIST)).''.$langs->trans("AllSalaries").''.$num.''; print '
'.$langs->trans("LastSalaries", ($num <= $MAXLIST ? "" : $MAXLIST)).''.$langs->trans("AllSalaries").''.$num.'