From 1cb56adb2e262cbaa71785a1ead482f2c5048abf Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 13 Apr 2022 15:44:27 +0200 Subject: [PATCH 001/267] NEW products categories in inventory card --- htdocs/core/actions_addupdatedelete.inc.php | 16 ++++++++++++++-- htdocs/core/class/commonobject.class.php | 8 +++++++- htdocs/install/mysql/migration/15.0.0-16.0.0.sql | 2 ++ .../install/mysql/tables/llx_inventory-stock.sql | 5 +++-- .../product/inventory/class/inventory.class.php | 14 ++++++++++++++ 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index f97d4aa94ee..b3c96312ba6 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -55,7 +55,7 @@ if ($action == 'add' && !empty($permissiontoadd)) { continue; // The field was not submited to be saved } } else { - if (!GETPOSTISSET($key)) { + if (!GETPOSTISSET($key) && !preg_match('/^chkbxlst:/', $object->fields[$key]['type'])) { continue; // The field was not submited to be saved } } @@ -85,6 +85,12 @@ if ($action == 'add' && !empty($permissiontoadd)) { } elseif ($object->fields[$key]['type'] == 'reference') { $tmparraykey = array_keys($object->param_list); $value = $tmparraykey[GETPOST($key)].','.GETPOST($key.'2'); + } elseif (preg_match('/^chkbxlst:(.*)/', $object->fields[$key]['type'])) { + $value = ''; + $values_arr = GETPOST($key, 'array'); + if (!empty($values_arr)) { + $value = implode(',', $values_arr); + } } else { if ($key == 'lang') { $value = GETPOST($key, 'aZ09') ?GETPOST($key, 'aZ09') : ""; @@ -168,7 +174,7 @@ if ($action == 'update' && !empty($permissiontoadd)) { continue; } } else { - if (!GETPOSTISSET($key)) { + if (!GETPOSTISSET($key) && !preg_match('/^chkbxlst:/', $object->fields[$key]['type'])) { continue; // The field was not submited to be saved } } @@ -206,6 +212,12 @@ if ($action == 'update' && !empty($permissiontoadd)) { $value = ((GETPOST($key, 'aZ09') == 'on' || GETPOST($key, 'aZ09') == '1') ? 1 : 0); } elseif ($object->fields[$key]['type'] == 'reference') { $value = array_keys($object->param_list)[GETPOST($key)].','.GETPOST($key.'2'); + } elseif (preg_match('/^chkbxlst:/', $object->fields[$key]['type'])) { + $value = ''; + $values_arr = GETPOST($key, 'array'); + if (!empty($values_arr)) { + $value = implode(',', $values_arr); + } } else { if ($key == 'lang') { $value = GETPOST($key, 'aZ09'); diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index a3c9c2e8122..011d5cd2f4b 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6649,6 +6649,9 @@ abstract class CommonObject } elseif (preg_match('/^(sellist):(.*):(.*)/i', $val['type'], $reg)) { $param['options'] = array($reg[2].':'.$reg[3] => 'N'); $type = 'sellist'; + } elseif (preg_match('/^chkbxlst:(.*)/i', $val['type'], $reg)) { + $param['options'] = array($reg[1] => 'N'); + $type = 'chkbxlst'; } elseif (preg_match('/varchar\((\d+)\)/', $val['type'], $reg)) { $param['options'] = array(); $type = 'varchar'; @@ -7098,7 +7101,7 @@ abstract class CommonObject } $this->db->free($resql); - $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%'); + $out = $form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, $morecss, 0, '100%'); } else { print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.
'; } @@ -7261,6 +7264,9 @@ abstract class CommonObject } elseif (preg_match('/^sellist:(.*):(.*)/i', $val['type'], $reg)) { $param['options'] = array($reg[1].':'.$reg[2] => 'N'); $type = 'sellist'; + } elseif (preg_match('/^chkbxlst:(.*)/i', $val['type'], $reg)) { + $param['options'] = array($reg[1] => 'N'); + $type = 'chkbxlst'; } $langfile = empty($val['langfile']) ? '' : $val['langfile']; diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index 5f8b1d886c3..e38b2f8ea41 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -324,3 +324,5 @@ ALTER TABLE llx_actioncomm MODIFY COLUMN note mediumtext; DELETE FROM llx_boxes WHERE box_id IN (select rowid FROM llx_boxes_def WHERE file IN ('box_bom.php@bom', 'box_bom.php')); DELETE FROM llx_boxes_def WHERE file IN ('box_bom.php@bom', 'box_bom.php'); + +ALTER TABLE llx_inventory ADD COLUMN fk_categories_product VARCHAR(255) DEFAULT NULL AFTER fk_product; diff --git a/htdocs/install/mysql/tables/llx_inventory-stock.sql b/htdocs/install/mysql/tables/llx_inventory-stock.sql index c25ccb9767b..7df2f72534a 100644 --- a/htdocs/install/mysql/tables/llx_inventory-stock.sql +++ b/htdocs/install/mysql/tables/llx_inventory-stock.sql @@ -28,8 +28,9 @@ CREATE TABLE llx_inventory fk_user_modif integer, -- user making last change fk_user_valid integer, -- valideur de la fiche fk_warehouse integer DEFAULT NULL, - fk_product integer DEFAULT NULL, - status integer DEFAULT 0, + fk_product integer DEFAULT NULL, + fk_categories_product varchar(255) DEFAULT NULL, -- product categories id separated by comma + status integer DEFAULT 0, title varchar(255) NOT NULL, date_inventory datetime DEFAULT NULL, date_validation datetime DEFAULT NULL, diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php index 92061972e60..ecb9df3a40c 100644 --- a/htdocs/product/inventory/class/inventory.class.php +++ b/htdocs/product/inventory/class/inventory.class.php @@ -102,6 +102,7 @@ class Inventory extends CommonObject 'title' => array('type'=>'varchar(255)', 'label'=>'Label', 'visible'=>1, 'enabled'=>1, 'position'=>25, 'css'=>'minwidth300', 'csslist'=>'tdoverflowmax200'), 'fk_warehouse' => array('type'=>'integer:Entrepot:product/stock/class/entrepot.class.php', 'label'=>'Warehouse', 'visible'=>1, 'enabled'=>1, 'position'=>30, 'index'=>1, 'help'=>'InventoryForASpecificWarehouse', 'picto'=>'stock', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'visible'=>1, 'enabled'=>1, 'position'=>32, 'index'=>1, 'help'=>'InventoryForASpecificProduct', 'picto'=>'product', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'csslist'=>'tdoverflowmax200'), + 'fk_categories_product' => array('type'=>'chkbxlst:categorie:label:rowid::type=0', 'label'=>'ProductsCategoriesShort', 'visible'=>3, 'enabled'=>1, 'position'=>33, 'help'=>'', 'picto'=>'category', 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx'), 'date_inventory' => array('type'=>'date', 'label'=>'DateValue', 'visible'=>1, 'enabled'=>'$conf->global->STOCK_INVENTORY_ADD_A_VALUE_DATE', 'position'=>35), // This date is not used so disabled by default. 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>500), 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501), @@ -139,6 +140,11 @@ class Inventory extends CommonObject */ public $fk_product; + /** + * @var int Categories id + */ + public $fk_categories_product; + public $date_inventory; public $title; @@ -291,6 +297,14 @@ class Inventory extends CommonObject if ($this->fk_warehouse > 0) { $sql .= " AND ps.fk_entrepot = ".((int) $this->fk_warehouse); } + if (!empty($this->fk_categories_product)) { + $sql .= " AND EXISTS ("; + $sql .= " SELECT cp.fk_product"; + $sql .= " FROM ".$this->db->prefix()."categorie_product AS cp"; + $sql .= " WHERE cp.fk_product = ps.fk_product"; + $sql .= " AND cp.fk_categorie IN (".$this->db->sanitize($this->fk_categories_product).")"; + $sql .= ")"; + } $inventoryline = new InventoryLine($this->db); From 7ad7943d2b478ece8b37b0e2b1b0af3c626ef33f Mon Sep 17 00:00:00 2001 From: lvessiller Date: Wed, 13 Apr 2022 16:17:14 +0200 Subject: [PATCH 002/267] FIX categories product property comment --- htdocs/product/inventory/class/inventory.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/inventory/class/inventory.class.php b/htdocs/product/inventory/class/inventory.class.php index ecb9df3a40c..fb255364470 100644 --- a/htdocs/product/inventory/class/inventory.class.php +++ b/htdocs/product/inventory/class/inventory.class.php @@ -141,7 +141,7 @@ class Inventory extends CommonObject public $fk_product; /** - * @var int Categories id + * @var string Categories id separated by comma */ public $fk_categories_product; From ab61c4d735e0e271888d5d71c45f94daf6b2a8bf Mon Sep 17 00:00:00 2001 From: lvessiller Date: Thu, 14 Apr 2022 11:08:05 +0200 Subject: [PATCH 003/267] NEW show category tree in sellist and chkbxlst for common object --- htdocs/core/class/commonobject.class.php | 531 ++++++++++-------- .../inventory/class/inventory.class.php | 2 +- 2 files changed, 306 insertions(+), 227 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 011d5cd2f4b..99b0ace26d0 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6830,6 +6830,8 @@ abstract class CommonObject // 2 : key fields name (if differ of rowid) // 3 : key field parent (for dependent lists) // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value + // 5 : id category type + // 6 : ids categories list separated by comma for category root $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2].' as rowid'); if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) { @@ -6844,112 +6846,130 @@ abstract class CommonObject $keyList .= ', '.$parentField; } - $fields_label = explode('|', $InfoFieldList[1]); - if (is_array($fields_label)) { - $keyList .= ', '; - $keyList .= implode(', ', $fields_label); + $filter_categorie = false; + if (count($InfoFieldList) > 5) { + if ($InfoFieldList[0] == 'categorie') { + $filter_categorie = true; + } } - $sqlwhere = ''; - $sql = "SELECT ".$keyList; - $sql .= " FROM ".$this->db->prefix().$InfoFieldList[0]; - if (!empty($InfoFieldList[4])) { - // can use SELECT request - if (strpos($InfoFieldList[4], '$SEL$') !== false) { - $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]); + if ($filter_categorie === false) { + $fields_label = explode('|', $InfoFieldList[1]); + if (is_array($fields_label)) { + $keyList .= ', '; + $keyList .= implode(', ', $fields_label); } - // current object id can be use into filter - if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) { - $InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]); - } else { - $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]); - } - - //We have to join on extrafield table - if (strpos($InfoFieldList[4], 'extra') !== false) { - $sql .= " as main, ".$this->db->prefix().$InfoFieldList[0]."_extrafields as extra"; - $sqlwhere .= " WHERE extra.fk_object=main.".$InfoFieldList[2]." AND ".$InfoFieldList[4]; - } else { - $sqlwhere .= " WHERE ".$InfoFieldList[4]; - } - } else { - $sqlwhere .= ' WHERE 1=1'; - } - // Some tables may have field, some other not. For the moment we disable it. - if (in_array($InfoFieldList[0], array('tablewithentity'))) { - $sqlwhere .= " AND entity = ".((int) $conf->entity); - } - $sql .= $sqlwhere; - //print $sql; - - $sql .= ' ORDER BY '.implode(', ', $fields_label); - - dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG); - $resql = $this->db->query($sql); - if ($resql) { - $out .= ''; - $num = $this->db->num_rows($resql); - $i = 0; - while ($i < $num) { - $labeltoshow = ''; - $obj = $this->db->fetch_object($resql); - - // Several field into label (eq table:code|libelle:rowid) - $notrans = false; - $fields_label = explode('|', $InfoFieldList[1]); - if (count($fields_label) > 1) { - $notrans = true; - foreach ($fields_label as $field_toshow) { - $labeltoshow .= $obj->$field_toshow.' '; - } - } else { - $labeltoshow = $obj->{$InfoFieldList[1]}; + $sqlwhere = ''; + $sql = "SELECT " . $keyList; + $sql .= " FROM " . $this->db->prefix() . $InfoFieldList[0]; + if (!empty($InfoFieldList[4])) { + // can use SELECT request + if (strpos($InfoFieldList[4], '$SEL$') !== false) { + $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]); } - $labeltoshow = dol_trunc($labeltoshow, 45); - if ($value == $obj->rowid) { - foreach ($fields_label as $field_toshow) { - $translabel = $langs->trans($obj->$field_toshow); - if ($translabel != $obj->$field_toshow) { - $labeltoshow = dol_trunc($translabel).' '; - } else { - $labeltoshow = dol_trunc($obj->$field_toshow).' '; - } - } - $out .= ''; + // current object id can be use into filter + if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) { + $InfoFieldList[4] = str_replace('$ID$', $objectid, $InfoFieldList[4]); } else { - if (!$notrans) { - $translabel = $langs->trans($obj->{$InfoFieldList[1]}); - if ($translabel != $obj->{$InfoFieldList[1]}) { - $labeltoshow = dol_trunc($translabel, 18); - } else { - $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}); + $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]); + } + + //We have to join on extrafield table + if (strpos($InfoFieldList[4], 'extra') !== false) { + $sql .= " as main, " . $this->db->prefix() . $InfoFieldList[0] . "_extrafields as extra"; + $sqlwhere .= " WHERE extra.fk_object=main." . $InfoFieldList[2] . " AND " . $InfoFieldList[4]; + } else { + $sqlwhere .= " WHERE " . $InfoFieldList[4]; + } + } else { + $sqlwhere .= ' WHERE 1=1'; + } + // Some tables may have field, some other not. For the moment we disable it. + if (in_array($InfoFieldList[0], array('tablewithentity'))) { + $sqlwhere .= " AND entity = " . ((int)$conf->entity); + } + $sql .= $sqlwhere; + //print $sql; + + $sql .= ' ORDER BY ' . implode(', ', $fields_label); + + dol_syslog(get_class($this) . '::showInputField type=sellist', LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $out .= ''; + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < $num) { + $labeltoshow = ''; + $obj = $this->db->fetch_object($resql); + + // Several field into label (eq table:code|libelle:rowid) + $notrans = false; + $fields_label = explode('|', $InfoFieldList[1]); + if (count($fields_label) > 1) { + $notrans = true; + foreach ($fields_label as $field_toshow) { + $labeltoshow .= $obj->$field_toshow . ' '; } + } else { + $labeltoshow = $obj->{$InfoFieldList[1]}; } - if (empty($labeltoshow)) { - $labeltoshow = '(not defined)'; - } + $labeltoshow = dol_trunc($labeltoshow, 45); + if ($value == $obj->rowid) { - $out .= ''; + foreach ($fields_label as $field_toshow) { + $translabel = $langs->trans($obj->$field_toshow); + if ($translabel != $obj->$field_toshow) { + $labeltoshow = dol_trunc($translabel) . ' '; + } else { + $labeltoshow = dol_trunc($obj->$field_toshow) . ' '; + } + } + $out .= ''; + } else { + if (!$notrans) { + $translabel = $langs->trans($obj->{$InfoFieldList[1]}); + if ($translabel != $obj->{$InfoFieldList[1]}) { + $labeltoshow = dol_trunc($translabel, 18); + } else { + $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}); + } + } + if (empty($labeltoshow)) { + $labeltoshow = '(not defined)'; + } + if ($value == $obj->rowid) { + $out .= ''; + } + + if (!empty($InfoFieldList[3]) && $parentField) { + $parent = $parentName . ':' . $obj->{$parentField}; + $isDependList = 1; + } + + $out .= ''; } - if (!empty($InfoFieldList[3]) && $parentField) { - $parent = $parentName.':'.$obj->{$parentField}; - $isDependList = 1; - } - - $out .= ''; + $i++; } - - $i++; + $this->db->free($resql); + } else { + print 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.
'; } - $this->db->free($resql); } else { - print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.
'; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + $data = $form->select_all_categories(Categorie::$MAP_ID_TO_CODE[$InfoFieldList[5]], '', 'parent', 64, $InfoFieldList[6], 1, 1); + $out .= ''; + foreach ($data as $data_key => $data_value) { + $out .= '