From 8a22dcdbcb5c3eda4c3de488bcbace570d98ee8a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sat, 26 Oct 2019 22:49:16 +0200 Subject: [PATCH 1/6] Add sql for MO --- .../install/mysql/migration/10.0.0-11.0.0.sql | 48 +++++++++++++++++++ .../mysql/tables}/llx_mrp_mo.key.sql | 2 - .../mysql/tables}/llx_mrp_mo.sql | 0 .../tables}/llx_mrp_mo_extrafields.key.sql | 0 .../mysql/tables}/llx_mrp_mo_extrafields.sql | 0 5 files changed, 48 insertions(+), 2 deletions(-) rename htdocs/{mrp/sql => install/mysql/tables}/llx_mrp_mo.key.sql (93%) rename htdocs/{mrp/sql => install/mysql/tables}/llx_mrp_mo.sql (100%) rename htdocs/{mrp/sql => install/mysql/tables}/llx_mrp_mo_extrafields.key.sql (100%) rename htdocs/{mrp/sql => install/mysql/tables}/llx_mrp_mo_extrafields.sql (100%) diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 0fd18a841f4..1263dc02569 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -358,3 +358,51 @@ create table llx_c_shipment_package_type entity integer DEFAULT 1 NOT NULL -- Multi company id )ENGINE=innodb; + +CREATE TABLE llx_mrp_mo( + -- BEGIN MODULEBUILDER FIELDS + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + ref varchar(128) DEFAULT '(PROV)' NOT NULL, + entity integer DEFAULT 1 NOT NULL, + label varchar(255), + qty real NOT NULL, + fk_soc integer, + note_public text, + note_private text, + date_creation datetime NOT NULL, + tms timestamp, + fk_user_creat integer NOT NULL, + fk_user_modif integer, + import_key varchar(14), + status integer NOT NULL, + fk_product integer NOT NULL, + date_start_planned datetime, + date_end_planned datetime, + fk_bom integer, + fk_project integer + -- END MODULEBUILDER FIELDS +) ENGINE=innodb; + + +ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_ref (ref); +ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_entity (entity); +ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_fk_soc (fk_soc); +ALTER TABLE llx_mrp_mo ADD CONSTRAINT llx_mrp_mo_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES user(rowid); +ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_status (status); +ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_fk_product (fk_product); +ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_date_start_planned (date_start_planned); +ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_date_end_planned (date_end_planned); +ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_fk_bom (fk_bom); +ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_fk_project (fk_project); + + +create table llx_mrp_myobject_extrafields +( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_object integer NOT NULL, + import_key varchar(14) -- import key +) ENGINE=innodb; + +ALTER TABLE llx_mrp_myobject_extrafields ADD INDEX idx_fk_object(fk_object); + diff --git a/htdocs/mrp/sql/llx_mrp_mo.key.sql b/htdocs/install/mysql/tables/llx_mrp_mo.key.sql similarity index 93% rename from htdocs/mrp/sql/llx_mrp_mo.key.sql rename to htdocs/install/mysql/tables/llx_mrp_mo.key.sql index 071a663dd56..8cda73f9450 100644 --- a/htdocs/mrp/sql/llx_mrp_mo.key.sql +++ b/htdocs/install/mysql/tables/llx_mrp_mo.key.sql @@ -15,10 +15,8 @@ -- BEGIN MODULEBUILDER INDEXES -ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_rowid (rowid); ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_ref (ref); ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_entity (entity); -ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_qty (qty); ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_fk_soc (fk_soc); ALTER TABLE llx_mrp_mo ADD CONSTRAINT llx_mrp_mo_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES user(rowid); ALTER TABLE llx_mrp_mo ADD INDEX idx_mrp_mo_status (status); diff --git a/htdocs/mrp/sql/llx_mrp_mo.sql b/htdocs/install/mysql/tables/llx_mrp_mo.sql similarity index 100% rename from htdocs/mrp/sql/llx_mrp_mo.sql rename to htdocs/install/mysql/tables/llx_mrp_mo.sql diff --git a/htdocs/mrp/sql/llx_mrp_mo_extrafields.key.sql b/htdocs/install/mysql/tables/llx_mrp_mo_extrafields.key.sql similarity index 100% rename from htdocs/mrp/sql/llx_mrp_mo_extrafields.key.sql rename to htdocs/install/mysql/tables/llx_mrp_mo_extrafields.key.sql diff --git a/htdocs/mrp/sql/llx_mrp_mo_extrafields.sql b/htdocs/install/mysql/tables/llx_mrp_mo_extrafields.sql similarity index 100% rename from htdocs/mrp/sql/llx_mrp_mo_extrafields.sql rename to htdocs/install/mysql/tables/llx_mrp_mo_extrafields.sql From f060ef1018ef3ab77477ba44da2e7bbc86b8a3ae Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 27 Oct 2019 00:01:16 +0200 Subject: [PATCH 2/6] FIX Clean decimal data for module builder --- htdocs/core/actions_addupdatedelete.inc.php | 6 +++--- htdocs/langs/en_US/mrp.lang | 3 ++- htdocs/mrp/class/mo.class.php | 16 +++++++++------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index d618a0702c8..72ad67db52e 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -56,7 +56,7 @@ if ($action == 'add' && ! empty($permissiontoadd)) $value = dol_mktime(12, 0, 0, GETPOST($key.'month'), GETPOST($key.'day'), GETPOST($key.'year')); } elseif ($object->fields[$key]['type']=='datetime') { $value = dol_mktime(GETPOST($key.'hour'), GETPOST($key.'min'), 0, GETPOST($key.'month'), GETPOST($key.'day'), GETPOST($key.'year')); - } elseif ($object->fields[$key]['type']=='price') { + } elseif (in_array($object->fields[$key]['type'], array('price', 'real'))) { $value = price2num(GETPOST($key)); } else { $value = GETPOST($key, 'alpha'); @@ -108,7 +108,7 @@ if ($action == 'update' && ! empty($permissiontoadd)) { if (! GETPOSTISSET($key)) continue; // The field was not submited to be edited if (in_array($key, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat', 'fk_user_modif', 'import_key'))) continue; // Ignore special fields - + var_dump($object->fields[$key]['type']); // Set value to update if (in_array($object->fields[$key]['type'], array('text', 'html'))) { $value = GETPOST($key, 'none'); @@ -116,7 +116,7 @@ if ($action == 'update' && ! empty($permissiontoadd)) $value = dol_mktime(12, 0, 0, GETPOST($key.'month'), GETPOST($key.'day'), GETPOST($key.'year')); } elseif ($object->fields[$key]['type']=='datetime') { $value = dol_mktime(GETPOST($key.'hour'), GETPOST($key.'min'), 0, GETPOST($key.'month'), GETPOST($key.'day'), GETPOST($key.'year')); - } elseif ($object->fields[$key]['type']=='price') { + } elseif (in_array($object->fields[$key]['type'], array('price', 'real'))) { $value = price2num(GETPOST($key)); } else { $value = GETPOST($key, 'alpha'); diff --git a/htdocs/langs/en_US/mrp.lang b/htdocs/langs/en_US/mrp.lang index 5d51be56e56..9b9d18c954e 100644 --- a/htdocs/langs/en_US/mrp.lang +++ b/htdocs/langs/en_US/mrp.lang @@ -31,4 +31,5 @@ EstimatedDuration=Estimated duration EstimatedDurationDesc=Estimated duration to manufacture this product using this BOM ConfirmValidateBom=Are you sure you want to validate the BOM with the reference %s (you will be able to use it to build new Manufacturing Orders) ConfirmCloseBom=Are you sure you want to cancel this BOM (you won't be able to use it to build new Manufacturing Orders anymore) ? -ConfirmReopenBom=Are you sure you want to re-open this BOM (you will be able to use it to build new Manufacturing Orders) \ No newline at end of file +ConfirmReopenBom=Are you sure you want to re-open this BOM (you will be able to use it to build new Manufacturing Orders) +StatusMOProduced=Produced \ No newline at end of file diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index 4f069e885bd..a3c49fcd3c8 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -61,7 +61,7 @@ class Mo extends CommonObject const STATUS_DRAFT = 0; const STATUS_VALIDATED = 1; // To produce const STATUS_INPROGRESS = 2; - const STATUS_DONE = 3; + const STATUS_PRODUCED = 3; const STATUS_CANCELED = -1; @@ -92,10 +92,10 @@ class Mo extends CommonObject */ public $fields=array( 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>1, 'visible'=>-1, 'position'=>1, 'notnull'=>1, 'index'=>1, 'comment'=>"Id",), - 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>1, 'position'=>10, 'notnull'=>1, 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'showoncombobox'=>'1',), - 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>-1, 'position'=>20, 'notnull'=>1, 'default'=>'1', 'index'=>1,), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>4, 'position'=>10, 'notnull'=>1, 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'showoncombobox'=>'1',), + 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'position'=>20, 'notnull'=>1, 'default'=>'1', 'index'=>1,), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>30, 'notnull'=>-1, 'searchall'=>1, 'showoncombobox'=>'1',), - 'qty' => array('type'=>'real', 'label'=>'QtyToProduce', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'notnull'=>1, 'index'=>1, 'comment'=>"Qty to produce",), + 'qty' => array('type'=>'real', 'label'=>'QtyToProduce', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'notnull'=>1, 'comment'=>"Qty to produce",), 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1', 'label'=>'ThirdParty', 'enabled'=>1, 'visible'=>-1, 'position'=>50, 'notnull'=>-1, 'index'=>1), 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>1, 'visible'=>0, 'position'=>61, 'notnull'=>-1,), 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>1, 'visible'=>0, 'position'=>62, 'notnull'=>-1,), @@ -109,7 +109,7 @@ class Mo extends CommonObject 'date_end_planned' => array('type'=>'datetime', 'label'=>'DateEndPlannedMo', 'enabled'=>1, 'visible'=>1, 'position'=>56, 'notnull'=>-1, 'index'=>1,), 'fk_bom' => array('type'=>'integer:Bom:bom/class/bom.class.php:0:t.status=1', 'filter'=>'active=1', 'label'=>'BOM', 'enabled'=>1, 'visible'=>1, 'position'=>33, 'notnull'=>-1, 'index'=>1, 'comment'=>"Original BOM",), 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1', 'label'=>'Project', 'enabled'=>1, 'visible'=>-1, 'position'=>52, 'notnull'=>-1, 'index'=>1,), - 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>4, 'position'=>1000, 'default'=>0, 'notnull'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Brouillon', '1'=>'Validated', '2'=>'InProgress', '3'=>'Done', '-1'=>'Canceled')), + 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>4, 'position'=>1000, 'default'=>0, 'notnull'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Brouillon', '1'=>'Validated', '2'=>'InProgress', '3'=>'StatusMOProduced', '-1'=>'Canceled')), ); public $rowid; public $ref; @@ -549,8 +549,10 @@ class Mo extends CommonObject global $langs; //$langs->load("mrp"); $this->labelstatus[self::STATUS_DRAFT] = $langs->trans('Draft'); - $this->labelstatus[self::STATUS_VALIDATED] = $langs->trans('Enabled'); - $this->labelstatus[self::STATUS_CANCELED] = $langs->trans('Disabled'); + $this->labelstatus[self::STATUS_VALIDATED] = $langs->trans('Validated'); + $this->labelstatus[self::STATUS_INPROGRESS] = $langs->trans('InProgress'); + $this->labelstatus[self::STATUS_PRODUCED] = $langs->trans('StatusMOProduced'); + $this->labelstatus[self::STATUS_CANCELED] = $langs->trans('Canceled'); } $statusType = 'status'.$status; From e17cc5b2e56cba5d7b0a7259f2536d8214a9eb5c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 27 Oct 2019 00:26:11 +0200 Subject: [PATCH 3/6] Debug cloning of BOMs --- htdocs/bom/bom_card.php | 6 ------ htdocs/bom/class/bom.class.php | 7 ++++--- htdocs/core/class/commonobject.class.php | 1 + htdocs/modulebuilder/template/class/myobject.class.php | 5 +++-- htdocs/mrp/class/mo.class.php | 6 +++--- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 17fae31ef7d..30031103156 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -294,12 +294,6 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea { $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); } - $formconfirm = ''; - - // Confirmation to delete - if ($action == 'delete') { - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteOrder'), $langs->trans('ConfirmDeleteOrder'), 'confirm_delete', '', 0, 1); - } // Confirmation of validation if ($action == 'validate') diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index b3163511150..90e23dad802 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -240,9 +240,10 @@ class BOM extends CommonObject unset($object->import_key); // Clear fields - $object->ref = "copy_of_".$object->ref; - $object->title = $langs->trans("CopyOf")." ".$object->title; - + $object->ref = empty($this->fields['ref']['default']) ? $langs->trans("copy_of_").$object->ref: $this->fields['ref']['default']; + $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label: $this->fields['label']['default']; + $object->status = self::STATUS_DRAFT; + // ... // Clear extrafields that are unique if (is_array($object->array_options) && count($object->array_options) > 0) { diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index b331c479670..01ed67cce3e 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7476,6 +7476,7 @@ abstract class CommonObject { $sql="UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET ref = '(PROV".$this->id.")' WHERE ref = '(PROV)' AND rowid = ".$this->id; $resqlupdate = $this->db->query($sql); + if ($resqlupdate===false) { $error++; diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index d6474a480dc..4fbdd101c35 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -283,8 +283,9 @@ class MyObject extends CommonObject // Clear fields - $object->ref = "copy_of_".$object->ref; - $object->title = $langs->trans("CopyOf")." ".$object->title; + $object->ref = empty($this->fields['ref']['default']) ? "copy_of_".$object->ref: $this->fields['ref']['default']; + $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label: $this->fields['label']['default']; + $object->status = self::STATUS_DRAFT; // ... // Clear extrafields that are unique if (is_array($object->array_options) && count($object->array_options) > 0) diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index a3c49fcd3c8..b013d300845 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -246,10 +246,10 @@ class Mo extends CommonObject unset($object->fk_user_creat); unset($object->import_key); - // Clear fields - $object->ref = "copy_of_".$object->ref; - $object->title = $langs->trans("CopyOf")." ".$object->title; + $object->ref = empty($this->fields['ref']['default']) ? "copy_of_".$object->ref: $this->fields['ref']['default']; + $object->label = empty($this->fields['label']['default']) ? $langs->trans("CopyOf")." ".$object->label: $this->fields['label']['default']; + $object->status = self::STATUS_DRAFT; // ... // Clear extrafields that are unique if (is_array($object->array_options) && count($object->array_options) > 0) From 5cb9434bb47dcd6a692f8aed6f7d8d9de4588082 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 27 Oct 2019 00:55:06 +0200 Subject: [PATCH 4/6] FIX Stock qty hidden without permission to see stock --- htdocs/core/class/html.form.class.php | 86 ++++++++++++++------------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 865e06a4478..ca285642b2a 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -2416,10 +2416,12 @@ class Form // Units $outvalUnits = ''; - if ($conf->global->PRODUCT_USE_UNITS) { + if (! empty($conf->global->PRODUCT_USE_UNITS)) { if (!empty($objp->unit_short)) { $outvalUnits .= ' - ' . $objp->unit_short; } + } + if (! empty($conf->global->PRODUCT_SHOW_DIMENSIONS_IN_COMBO)) { if (!empty($objp->weight) && $objp->weight_units!==null) { $unitToShow = showDimensionInBestUnit($objp->weight, $objp->weight_units, 'weight', $langs); $outvalUnits .= ' - ' . $unitToShow; @@ -2436,17 +2438,17 @@ class Form $unitToShow = showDimensionInBestUnit($objp->volume, $objp->volume_units, 'volume', $langs); $outvalUnits .= ' - ' . $unitToShow; } - if ($outdurationvalue && $outdurationunit) { - $da = array( - 'h' => $langs->trans('Hour'), - 'd' => $langs->trans('Day'), - 'w' => $langs->trans('Week'), - 'm' => $langs->trans('Month'), - 'y' => $langs->trans('Year') - ); - if (isset($da[$outdurationunit])) { - $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit].($outdurationvalue > 1 ? 's' : '')); - } + } + if ($outdurationvalue && $outdurationunit) { + $da = array( + 'h' => $langs->trans('Hour'), + 'd' => $langs->trans('Day'), + 'w' => $langs->trans('Week'), + 'm' => $langs->trans('Month'), + 'y' => $langs->trans('Year') + ); + if (isset($da[$outdurationunit])) { + $outvalUnits .= ' - ' . $outdurationvalue . ' ' . $langs->transnoentities($da[$outdurationunit].($outdurationvalue > 1 ? 's' : '')); } } @@ -2458,8 +2460,10 @@ class Form } if (! empty($conf->stock->enabled) && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))) { - if ($objp->stock > 0) $opt.= ' class="product_line_stock_ok"'; - elseif ($objp->stock <= 0) $opt.= ' class="product_line_stock_too_low"'; + if (! empty($user->rights->stock->lire)) { + if ($objp->stock > 0) $opt.= ' class="product_line_stock_ok"'; + elseif ($objp->stock <= 0) $opt.= ' class="product_line_stock_too_low"'; + } } $opt.= '>'; $opt.= $objp->ref; @@ -2602,37 +2606,39 @@ class Form if (! empty($conf->stock->enabled) && isset($objp->stock) && ($objp->fk_product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))) { - $opt.= ' - '.$langs->trans("Stock").':'.$objp->stock; + if (! empty($user->rights->stock->lire)) { + $opt.= ' - '.$langs->trans("Stock").':'.$objp->stock; - if ($objp->stock > 0) { - $outval.= ' - '; - }elseif ($objp->stock <= 0) { - $outval.= ' - '; - } - $outval.= $langs->transnoentities("Stock").':'.$objp->stock; - $outval.= ''; - if (! empty($conf->global->STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO)) // Warning, this option may slow down combo list generation - { - $langs->load("stocks"); + if ($objp->stock > 0) { + $outval.= ' - '; + }elseif ($objp->stock <= 0) { + $outval.= ' - '; + } + $outval.= $langs->transnoentities("Stock").':'.$objp->stock; + $outval.= ''; + if (! empty($conf->global->STOCK_SHOW_VIRTUAL_STOCK_IN_PRODUCTS_COMBO)) // Warning, this option may slow down combo list generation + { + $langs->load("stocks"); - $tmpproduct=new Product($this->db); - $tmpproduct->fetch($objp->rowid); - $tmpproduct->load_virtual_stock(); - $virtualstock = $tmpproduct->stock_theorique; + $tmpproduct=new Product($this->db); + $tmpproduct->fetch($objp->rowid); + $tmpproduct->load_virtual_stock(); + $virtualstock = $tmpproduct->stock_theorique; - $opt.= ' - '.$langs->trans("VirtualStock").':'.$virtualstock; + $opt.= ' - '.$langs->trans("VirtualStock").':'.$virtualstock; - $outval.=' - '.$langs->transnoentities("VirtualStock").':'; - if ($virtualstock > 0) { - $outval.= ' - '; - }elseif ($virtualstock <= 0) { - $outval.= ' - '; - } - $outval.=$virtualstock; - $outval.=''; + $outval.=' - '.$langs->transnoentities("VirtualStock").':'; + if ($virtualstock > 0) { + $outval.= ' - '; + }elseif ($virtualstock <= 0) { + $outval.= ' - '; + } + $outval.=$virtualstock; + $outval.=''; - unset($tmpproduct); - } + unset($tmpproduct); + } + } } $opt.= "\n"; From eb112d4012dd0cc252902beae7adeb498c866ade Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 27 Oct 2019 01:49:31 +0200 Subject: [PATCH 5/6] Add qty frozen and disable stock change flag on BOM --- htdocs/bom/bom_card.php | 47 +++++++++++++----- htdocs/bom/class/bom.class.php | 48 +++---------------- htdocs/bom/tpl/objectline_create.tpl.php | 18 +++++-- htdocs/bom/tpl/objectline_edit.tpl.php | 8 ++++ htdocs/bom/tpl/objectline_title.tpl.php | 7 +++ htdocs/bom/tpl/objectline_view.tpl.php | 10 ++++ .../install/mysql/migration/10.0.0-11.0.0.sql | 3 ++ .../install/mysql/tables/llx_bom_bomline.sql | 2 + htdocs/langs/en_US/mrp.lang | 6 ++- 9 files changed, 89 insertions(+), 60 deletions(-) diff --git a/htdocs/bom/bom_card.php b/htdocs/bom/bom_card.php index 30031103156..6186e809543 100644 --- a/htdocs/bom/bom_card.php +++ b/htdocs/bom/bom_card.php @@ -125,9 +125,11 @@ if (empty($reshook)) $error = 0; // Set if we used free entry or predefined product - $idprod=GETPOST('idprod', 'int'); - $qty=GETPOST('qty', 'int'); - $efficiency=GETPOST('efficiency', 'int'); + $idprod = GETPOST('idprod', 'int'); + $qty = GETPOST('qty', 'int'); + $qty_frozen = GETPOST('qty_frozen', 'int'); + $disable_stock_change = GETPOST('disable_stock_change', 'int'); + $efficiency = GETPOST('efficiency', 'int'); if ($qty == '') { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors'); @@ -138,17 +140,27 @@ if (empty($reshook)) $error++; } - $bomline = new BOMLine($db); - $bomline->fk_bom = $id; - $bomline->fk_product = $idprod; - $bomline->qty = $qty; - $bomline->efficiency = $efficiency; - - $result = $bomline->create($user); - if ($result <= 0) + if (! $error) { - setEventMessages($bomline->error, $bomline->errors, 'errors'); - $action = ''; + $bomline = new BOMLine($db); + $bomline->fk_bom = $id; + $bomline->fk_product = $idprod; + $bomline->qty = $qty; + $bomline->qty_frozen = $qty_frozen; + $bomline->disable_stock_change = $disable_stock_change; + $bomline->efficiency = $efficiency; + + $result = $bomline->create($user); + if ($result <= 0) + { + setEventMessages($bomline->error, $bomline->errors, 'errors'); + $action = ''; + } + else + { + unset($_POST['qty_frozen']); + unset($_POST['disable_stock_change']); + } } } @@ -160,6 +172,8 @@ if (empty($reshook)) // Set if we used free entry or predefined product $qty=GETPOST('qty', 'int'); + $qty_frozen = GETPOST('qty_frozen', 'int'); + $disable_stock_change = GETPOST('disable_stock_change', 'int'); $efficiency=GETPOST('efficiency', 'int'); if ($qty == '') { @@ -170,6 +184,8 @@ if (empty($reshook)) $bomline = new BOMLine($db); $bomline->fetch($lineid); $bomline->qty = $qty; + $bomline->qty_frozen = $qty_frozen; + $bomline->disable_stock_change = $disable_stock_change; $bomline->efficiency = $efficiency; $result = $bomline->update($user); @@ -178,6 +194,11 @@ if (empty($reshook)) setEventMessages($bomline->error, $bomline->errors, 'errors'); $action = ''; } + else + { + unset($_POST['qty_frozen']); + unset($_POST['disable_stock_change']); + } } } diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index 90e23dad802..0d59946216b 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -1041,7 +1041,9 @@ class BOMLine extends CommonObject 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php', 'label'=>'Product', 'enabled'=>1, 'visible'=>1, 'position'=>20, 'notnull'=>1, 'index'=>1,), 'description' => array('type'=>'text', 'label'=>'Description', 'enabled'=>1, 'visible'=>-1, 'position'=>60, 'notnull'=>-1,), 'qty' => array('type'=>'double(24,8)', 'label'=>'Quantity', 'enabled'=>1, 'visible'=>1, 'position'=>100, 'notnull'=>1, 'isameasure'=>'1',), - 'efficiency' => array('type'=>'double(8,4)', 'label'=>'ManufacturingEfficiency', 'enabled'=>1, 'visible'=>1, 'default'=>1, 'position'=>110, 'notnull'=>1, 'css'=>'maxwidth50imp', 'help'=>'ValueOfMeansLoss'), + 'qty_frozen' => array('type'=>'smallint', 'label'=>'QuantityFrozen', 'enabled'=>1, 'visible'=>1, 'default'=>0, 'position'=>105, 'css'=>'maxwidth50imp', 'help'=>'QuantityConsumedInvariable'), + 'disable_stock_change' => array('type'=>'smallint', 'label'=>'DisableStockChange', 'enabled'=>1, 'visible'=>1, 'default'=>0, 'position'=>108, 'css'=>'maxwidth50imp', 'help'=>'DisableStockChangeHelp'), + 'efficiency' => array('type'=>'double(8,4)', 'label'=>'ManufacturingEfficiency', 'enabled'=>1, 'visible'=>1, 'default'=>1, 'position'=>110, 'notnull'=>1, 'css'=>'maxwidth50imp', 'help'=>'ValueOfMeansLoss'), 'position' => array('type'=>'integer', 'label'=>'Rank', 'enabled'=>1, 'visible'=>0, 'default'=>0, 'position'=>200, 'notnull'=>1,), 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>1000, 'notnull'=>-1,), ); @@ -1050,6 +1052,8 @@ class BOMLine extends CommonObject public $fk_product; public $description; public $qty; + public $qty_frozen; + public $disable_stock_change; public $efficiency; public $position; public $import_key; @@ -1316,47 +1320,7 @@ class BOMLine extends CommonObject public function LibStatut($status, $mode = 0) { // phpcs:enable - if (empty($this->labelstatus)) - { - global $langs; - //$langs->load("mrp"); - $this->labelstatus[1] = $langs->trans('Enabled'); - $this->labelstatus[0] = $langs->trans('Disabled'); - } - - if ($mode == 0) - { - return $this->labelstatus[$status]; - } - elseif ($mode == 1) - { - return $this->labelstatus[$status]; - } - elseif ($mode == 2) - { - if ($status == 1) return img_picto($this->labelstatus[$status], 'statut4', '', false, 0, 0, '', 'valignmiddle').' '.$this->labelstatus[$status]; - elseif ($status == 0) return img_picto($this->labelstatus[$status], 'statut5', '', false, 0, 0, '', 'valignmiddle').' '.$this->labelstatus[$status]; - } - elseif ($mode == 3) - { - if ($status == 1) return img_picto($this->labelstatus[$status], 'statut4', '', false, 0, 0, '', 'valignmiddle'); - elseif ($status == 0) return img_picto($this->labelstatus[$status], 'statut5', '', false, 0, 0, '', 'valignmiddle'); - } - elseif ($mode == 4) - { - if ($status == 1) return img_picto($this->labelstatus[$status], 'statut4', '', false, 0, 0, '', 'valignmiddle').' '.$this->labelstatus[$status]; - elseif ($status == 0) return img_picto($this->labelstatus[$status], 'statut5', '', false, 0, 0, '', 'valignmiddle').' '.$this->labelstatus[$status]; - } - elseif ($mode == 5) - { - if ($status == 1) return $this->labelstatus[$status].' '.img_picto($this->labelstatus[$status], 'statut4', '', false, 0, 0, '', 'valignmiddle'); - elseif ($status == 0) return $this->labelstatus[$status].' '.img_picto($this->labelstatus[$status], 'statut5', '', false, 0, 0, '', 'valignmiddle'); - } - elseif ($mode == 6) - { - if ($status == 1) return $this->labelstatus[$status].' '.img_picto($this->labelstatus[$status], 'statut4', '', false, 0, 0, '', 'valignmiddle'); - elseif ($status == 0) return $this->labelstatus[$status].' '.img_picto($this->labelstatus[$status], 'statut5', '', false, 0, 0, '', 'valignmiddle'); - } + return ''; } /** diff --git a/htdocs/bom/tpl/objectline_create.tpl.php b/htdocs/bom/tpl/objectline_create.tpl.php index cd654c7a596..9f6bfee98f2 100644 --- a/htdocs/bom/tpl/objectline_create.tpl.php +++ b/htdocs/bom/tpl/objectline_create.tpl.php @@ -63,11 +63,13 @@ if ($nolinesbefore) { print ''.$langs->trans('Qty').''; if ($conf->global->PRODUCT_USE_UNITS) { - print ''; - print ''; - print $langs->trans('Unit'); - print ''; + print ''; + print ''; + print $langs->trans('Unit'); + print ''; } + print ''.$form->textwithpicto($langs->trans('QtyFrozen'), $langs->trans("QuantityConsumedInvariable")).''; + print ''.$form->textwithpicto($langs->trans('DisableStockChange'), $langs->trans('DisableStockChangeHelp')).''; print ''.$form->textwithpicto($langs->trans('ManufacturingEfficiency'), $langs->trans('ValueOfMeansLoss')).''; print ' '; print ''; @@ -109,6 +111,7 @@ if (! empty($conf->product->enabled) || ! empty($conf->service->enabled)) $coldisplay++; print ''; print ''; + if($conf->global->PRODUCT_USE_UNITS) { $coldisplay++; @@ -118,7 +121,14 @@ if($conf->global->PRODUCT_USE_UNITS) } $coldisplay++; +print ''; +print ''; +$coldisplay++; +print ''; +print ''; + +$coldisplay++; print ''; print ''; print ''; diff --git a/htdocs/bom/tpl/objectline_edit.tpl.php b/htdocs/bom/tpl/objectline_edit.tpl.php index d887b9ab68d..c7fc4f73cd7 100644 --- a/htdocs/bom/tpl/objectline_edit.tpl.php +++ b/htdocs/bom/tpl/objectline_edit.tpl.php @@ -116,6 +116,14 @@ if ($conf->global->PRODUCT_USE_UNITS) print ''; } +$coldisplay++; +print 'qty_frozen?' checked="checked"':'')).'>'; +print ''; + +$coldisplay++; +print 'disable_stock_change?' checked="checked"':'')).'">'; +print ''; + $coldisplay++; print ''; print ''; diff --git a/htdocs/bom/tpl/objectline_title.tpl.php b/htdocs/bom/tpl/objectline_title.tpl.php index 721cc5b501f..138a0b9aa58 100644 --- a/htdocs/bom/tpl/objectline_title.tpl.php +++ b/htdocs/bom/tpl/objectline_title.tpl.php @@ -59,6 +59,13 @@ if ($conf->global->PRODUCT_USE_UNITS) print ''.$langs->trans('Unit').''; } +// Qty frozen +print ''.$form->textwithpicto($langs->trans('QtyFrozen'), $langs->trans("QuantityConsumedInvariable")).''; + +// Disable stock change +print ''.$form->textwithpicto($langs->trans('DisableStockChange'), $langs->trans('DisableStockChangeHelp')).''; + +// Efficiency print ''.$form->textwithpicto($langs->trans('ManufacturingEfficiency'), $langs->trans('ValueOfMeansLoss')).''; print ''; // No width to allow autodim diff --git a/htdocs/bom/tpl/objectline_view.tpl.php b/htdocs/bom/tpl/objectline_view.tpl.php index f68372c721d..330f8ef8a33 100644 --- a/htdocs/bom/tpl/objectline_view.tpl.php +++ b/htdocs/bom/tpl/objectline_view.tpl.php @@ -87,6 +87,16 @@ if($conf->global->PRODUCT_USE_UNITS) } print ''; } + +print ''; +$coldisplay++; +echo $line->qty_frozen ? yn($line->qty_frozen) : ''; +print ''; +print ''; +$coldisplay++; +echo $line->disable_stock_change ? yn($line->disable_stock_change) : ''; // Yes, it is a quantity, not a price, but we just want the formating role of function price +print ''; + print ''; $coldisplay++; echo $line->efficiency; diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 1263dc02569..33441d4824a 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -58,6 +58,9 @@ UPDATE llx_rights_def SET subperms = 'write' WHERE perms = 'fiscalyear' AND modu ALTER TABLE llx_bom_bom ADD COLUMN duration double(8,4) DEFAULT NULL; ALTER TABLE llx_bom_bomline ADD COLUMN position integer NOT NULL DEFAULT 0; +ALTER TABLE llx_bom_bomline ADD COLUMN qty_frozen smallint DEFAULT 0; +ALTER TABLE llx_bom_bomline ADD COLUMN disable_stock_change smallint DEFAULT 0; + ALTER TABLE llx_bom_bomline DROP COLUMN rank; create table llx_categorie_warehouse diff --git a/htdocs/install/mysql/tables/llx_bom_bomline.sql b/htdocs/install/mysql/tables/llx_bom_bomline.sql index 330f1bb18d6..3fa1c2be528 100644 --- a/htdocs/install/mysql/tables/llx_bom_bomline.sql +++ b/htdocs/install/mysql/tables/llx_bom_bomline.sql @@ -22,6 +22,8 @@ CREATE TABLE llx_bom_bomline( description text, import_key varchar(14), qty double(24,8) NOT NULL, + qty_frozen smallint DEFAULT 0, + disable_stock_change smallint DEFAULT 0, efficiency double(8,4) NOT NULL DEFAULT 1, position integer NOT NULL DEFAULT 0 -- END MODULEBUILDER FIELDS diff --git a/htdocs/langs/en_US/mrp.lang b/htdocs/langs/en_US/mrp.lang index 9b9d18c954e..08073ac4364 100644 --- a/htdocs/langs/en_US/mrp.lang +++ b/htdocs/langs/en_US/mrp.lang @@ -32,4 +32,8 @@ EstimatedDurationDesc=Estimated duration to manufacture this product using this ConfirmValidateBom=Are you sure you want to validate the BOM with the reference %s (you will be able to use it to build new Manufacturing Orders) ConfirmCloseBom=Are you sure you want to cancel this BOM (you won't be able to use it to build new Manufacturing Orders anymore) ? ConfirmReopenBom=Are you sure you want to re-open this BOM (you will be able to use it to build new Manufacturing Orders) -StatusMOProduced=Produced \ No newline at end of file +StatusMOProduced=Produced +QtyFrozen=Frozen Qty +QuantityConsumedInvariable=When this flag is set, the quantity consumed is always the value defined and is not relative to the quantity produced. +DisableStockChange=Disable stock change +DisableStockChangeHelp=When this flag is set, there is no stock change on this product, whatever is the quantity produced From 83a5cfbd1c86374cfa0fe87371ed68022a8f13e7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 27 Oct 2019 02:05:43 +0200 Subject: [PATCH 6/6] Support events on BOM --- htdocs/install/mysql/data/llx_c_action_trigger.sql | 8 ++++++++ htdocs/install/mysql/migration/10.0.0-11.0.0.sql | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/htdocs/install/mysql/data/llx_c_action_trigger.sql b/htdocs/install/mysql/data/llx_c_action_trigger.sql index abc961b49d5..406bfe88dbc 100644 --- a/htdocs/install/mysql/data/llx_c_action_trigger.sql +++ b/htdocs/install/mysql/data/llx_c_action_trigger.sql @@ -119,6 +119,14 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('FICHINTER_MODIFY','Intervention modified','Executed when a intervention is modified','ficheinter',19); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROJECT_CREATE','Project creation','Executed when a project is created','project',140); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('PROJECT_MODIFY','Project modified','Executed when a project is modified','project',142); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_VALIDATE','BOM validated','Executed when a BOM is validated','bom',400); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_UNVALIDATE','BOM unvalidated','Executed when a BOM is unvalidated','bom',401); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_CLOSE','BOM disabled','Executed when a BOM is disabled','bom',402); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_REOPEN','BOM reopen','Executed when a BOM is re-open','bom',403); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_DELETE','BOM deleted','Executed when a BOM deleted','bom',404); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MO_VALIDATE','MO validated','Executed when a MO is validated','bom',410); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MO_PRODUCED','MO disabled','Executed when a MO is produced','bom',411); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MO_DELETE','MO deleted','Executed when a MO is deleted','bom',412); -- actions not enabled by default : they are excluded when we enable the module Agenda (except TASK_...) insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_CREATE','Task created','Executed when a project task is created','project',150); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('TASK_MODIFY','Task modified','Executed when a project task is modified','project',151); diff --git a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql index 33441d4824a..97383de9051 100644 --- a/htdocs/install/mysql/migration/10.0.0-11.0.0.sql +++ b/htdocs/install/mysql/migration/10.0.0-11.0.0.sql @@ -409,3 +409,13 @@ create table llx_mrp_myobject_extrafields ALTER TABLE llx_mrp_myobject_extrafields ADD INDEX idx_fk_object(fk_object); + +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_VALIDATE','BOM validated','Executed when a BOM is validated','bom',400); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_UNVALIDATE','BOM unvalidated','Executed when a BOM is unvalidated','bom',401); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_CLOSE','BOM disabled','Executed when a BOM is disabled','bom',402); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_REOPEN','BOM reopen','Executed when a BOM is re-open','bom',403); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('BOM_DELETE','BOM deleted','Executed when a BOM deleted','bom',404); + +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MO_VALIDATE','MO validated','Executed when a MO is validated','bom',410); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MO_PRODUCED','MO disabled','Executed when a MO is produced','bom',411); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MO_DELETE','MO deleted','Executed when a MO is deleted','bom',412);