diff --git a/htdocs/core/actions_addupdatedelete.inc.php b/htdocs/core/actions_addupdatedelete.inc.php index 0d718c2abc2..f5f0f822108 100644 --- a/htdocs/core/actions_addupdatedelete.inc.php +++ b/htdocs/core/actions_addupdatedelete.inc.php @@ -44,6 +44,7 @@ if ($cancel) $action = ''; } + // Action to add record if ($action == 'add' && !empty($permissiontoadd)) { diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index a6084a49f7e..1508575ba37 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -7317,7 +7317,7 @@ abstract class CommonObject global $conf; $queryarray = array(); - foreach ($this->fields as $field=>$info) // Loop on definition of fields + foreach ($this->fields as $field => $info) // Loop on definition of fields { // Depending on field type ('datetime', ...) if ($this->isDate($info)) @@ -7553,6 +7553,8 @@ abstract class CommonObject { $error++; $this->errors[] = $this->db->lasterror(); + } else { + $this->ref = '(PROV'.$this->id.')'; } } } 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 b4d956129a7..4bacfa9b765 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 @@ -521,6 +521,8 @@ CREATE TABLE llx_mrp_production( fk_product integer NOT NULL, fk_warehouse integer, qty integer NOT NULL DEFAULT 1, + qty_frozen smallint DEFAULT 0, + disable_stock_change smallint DEFAULT 0, batch varchar(30), role varchar(10), -- 'toconsume' or 'toproduce' (initialized at MO creation), 'consumed' or 'produced' (added after MO validation) fk_mrp_production integer, -- if role = 'consumed', id of line with role 'toconsume', if role = 'produced' id of line with role 'toproduce' @@ -532,6 +534,8 @@ CREATE TABLE llx_mrp_production( import_key varchar(14) ) ENGINE=innodb; +ALTER TABLE llx_mrp_production ADD COLUMN qty_frozen smallint DEFAULT 0; +ALTER TABLE llx_mrp_production ADD COLUMN disable_stock_change smallint DEFAULT 0; ALTER TABLE llx_mrp_production ADD CONSTRAINT fk_mrp_production_mo FOREIGN KEY (fk_mo) REFERENCES llx_mrp_mo (rowid); ALTER TABLE llx_mrp_production ADD CONSTRAINT fk_mrp_production_product FOREIGN KEY (fk_product) REFERENCES llx_product (rowid); ALTER TABLE llx_mrp_production ADD CONSTRAINT fk_mrp_production_stock_movement FOREIGN KEY (fk_stock_movement) REFERENCES llx_stock_mouvement (rowid); diff --git a/htdocs/install/mysql/tables/llx_mrp_production.sql b/htdocs/install/mysql/tables/llx_mrp_production.sql index 275acde6aef..b05e261c65b 100644 --- a/htdocs/install/mysql/tables/llx_mrp_production.sql +++ b/htdocs/install/mysql/tables/llx_mrp_production.sql @@ -21,6 +21,8 @@ CREATE TABLE llx_mrp_production( fk_product integer NOT NULL, fk_warehouse integer, qty integer NOT NULL DEFAULT 1, + qty_frozen smallint DEFAULT 0, + disable_stock_change smallint DEFAULT 0, batch varchar(30), role varchar(10), -- 'toconsume' or 'toproduce' (initialized at MO creation), 'consumed' or 'produced' (added after MO validation) fk_mrp_production integer, -- if role = 'consumed', id of line with role 'toconsume', if role = 'produced' id of line with role 'toproduce' diff --git a/htdocs/langs/en_US/mrp.lang b/htdocs/langs/en_US/mrp.lang index 2eb28366a55..4bed22df445 100644 --- a/htdocs/langs/en_US/mrp.lang +++ b/htdocs/langs/en_US/mrp.lang @@ -53,3 +53,4 @@ CreateMO=Create MO ToConsume=A consommer Manufactured=Fabriqué TheProductXIsAlreadyTheProductToProduce=The product to add is already the product to produce. +ForAQuantityOf1=For a quantity to produce of 1 \ No newline at end of file diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index cf8e45b5901..982bff9d9ae 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -231,13 +231,57 @@ class Mo extends CommonObject */ public function create(User $user, $notrigger = false) { + global $conf; + + $error = 0; + $this->db->begin(); $result = $this->createCommon($user, $notrigger); + if ($result <= 0) { + $error++; + } // Insert lines in mrp_production table + if (! $error && $this->fk_bom > 0) + { + include_once DOL_DOCULENT_ROOT.'/bom/class/bom.class.php'; + $bom = new Bom($this->db); + $bom->fetch($this->fk_bom); + if ($bom->id > 0) + { + foreach($bom->lines as $line) + { + $moline = new MOLine($this->db); - if ($result > 0) { + $moline->fk_mo = $this->id; + $moline->qty = $line->qty * $this->qty * $bom->efficiency; + if ($moline->qty <= 0) { + $error++; + $this->error = "BadValueForquantityToConsume"; + break; + } + else { + $moline->fk_product = $line->fk_product; + $moline->role = 'toconsume'; + $moline->position = $line->position; + $moline->qty_frozen = $line->qty_frozen; + $moline->disable_stock_change = $line->disable_stock_change; + + $resultline = $moline->create($user); + if ($resultline <= 0) { + $error++; + $this->error = $moline->error; + $this->errors = $moline->errors; + dol_print_error($this->db, $moline->error, $moline->errors); + break; + } + } + } + } + } + + if (! $error) { $this->db->commit(); } else { $this->db->rollback(); @@ -838,8 +882,153 @@ class Mo extends CommonObject /** * Class MoLine. You can also remove this and generate a CRUD class for lines objects. */ -class MoLine +class MoLine extends CommonObjectLine { - // To complete with content of an object MoLine - // We should have a field rowid, fk_mo and position + /** + * @var string ID to identify managed object + */ + public $element = 'mrp_production'; + + /** + * @var string Name of table without prefix where object is stored + */ + public $table_element = 'mrp_production'; + + /** + * @var int Does myobject support multicompany module ? 0=No test on entity, 1=Test with field entity, 2=Test with link by societe + */ + public $ismultientitymanaged = 0; + + /** + * @var int Does moline support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + public $fields=array( + 'rowid' =>array('type'=>'integer', 'label'=>'ID', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>10), + 'fk_mo' =>array('type'=>'integer', 'label'=>'Fk mo', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>15), + 'position' =>array('type'=>'integer', 'label'=>'Position', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>20), + 'fk_product' =>array('type'=>'integer', 'label'=>'Fk product', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>25), + 'fk_warehouse' =>array('type'=>'integer', 'label'=>'Fk warehouse', 'enabled'=>1, 'visible'=>-1, 'position'=>30), + 'qty' =>array('type'=>'integer', 'label'=>'Qty', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>35), + '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'), + 'batch' =>array('type'=>'varchar(30)', 'label'=>'Batch', 'enabled'=>1, 'visible'=>-1, 'position'=>140), + 'role' =>array('type'=>'varchar(10)', 'label'=>'Role', 'enabled'=>1, 'visible'=>-1, 'position'=>145), + 'fk_mrp_production' =>array('type'=>'integer', 'label'=>'Fk mrp production', 'enabled'=>1, 'visible'=>-1, 'position'=>150), + 'fk_stock_movement' =>array('type'=>'integer', 'label'=>'Fk stock movement', 'enabled'=>1, 'visible'=>-1, 'position'=>155), + 'date_creation' =>array('type'=>'datetime', 'label'=>'Date creation', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>160), + 'tms' =>array('type'=>'timestamp', 'label'=>'Tms', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>165), + 'fk_user_creat' =>array('type'=>'integer', 'label'=>'Fk user creat', 'enabled'=>1, 'visible'=>-1, 'notnull'=>1, 'position'=>170), + 'fk_user_modif' =>array('type'=>'integer', 'label'=>'Fk user modif', 'enabled'=>1, 'visible'=>-1, 'position'=>175), + 'import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportKey', 'enabled'=>1, 'visible'=>-1, 'position'=>180), + ); + + public $rowid; + public $fk_mo; + public $position; + public $fk_product; + public $fk_warehouse; + public $qty; + public $qty_frozen; + public $disable_stock_change; + public $batch; + public $role; + public $fk_mrp_production; + public $fk_stock_movement; + public $date_creation; + public $tms; + public $fk_user_creat; + public $fk_user_modif; + public $import_key; + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0; + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) + { + if (isset($val['enabled']) && empty($val['enabled'])) + { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) + { + foreach($this->fields as $key => $val) + { + if (is_array($val['arrayofkeyval'])) + { + foreach($val['arrayofkeyval'] as $key2 => $val2) + { + $this->fields[$key]['arrayofkeyval'][$key2]=$langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK + */ + public function create(User $user, $notrigger = false) + { + return $this->createCommon($user, $notrigger); + } + + /** + * Load object in memory from the database + * + * @param int $id Id object + * @param string $ref Ref + * @return int <0 if KO, 0 if not found, >0 if OK + */ + public function fetch($id, $ref = null) + { + $result = $this->fetchCommon($id, $ref); + if ($result > 0 && !empty($this->table_element_line)) $this->fetchLines(); + return $result; + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function update(User $user, $notrigger = false) + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, >0 if OK + */ + public function delete(User $user, $notrigger = false) + { + return $this->deleteCommon($user, $notrigger); + //return $this->deleteCommon($user, $notrigger, 1); + } } diff --git a/htdocs/mrp/mo_card.php b/htdocs/mrp/mo_card.php index baa4c09725f..9534e643e0d 100644 --- a/htdocs/mrp/mo_card.php +++ b/htdocs/mrp/mo_card.php @@ -93,10 +93,13 @@ if (GETPOST('fk_bom', 'int')) { $objectbom->fetch(GETPOST('fk_bom', 'int')); - $_POST['fk_product'] = $objectbom->fk_product; - $_POST['qty'] = $objectbom->qty; - $_POST['fk_warehouse'] = $objectbom->fk_warehouse; - $_POST['note_private'] = $objectbom->note_private; + if ($action != 'add') { + // We force calling parameters if we are not in the submit of creation of MO + $_POST['fk_product'] = $objectbom->fk_product; + $_POST['qty'] = $objectbom->qty; + $_POST['fk_warehouse'] = $objectbom->fk_warehouse; + $_POST['note_private'] = $objectbom->note_private; + } } // Security check - Protection if external user @@ -279,7 +282,7 @@ if ($action == 'create') print ''; if (GETPOST('fk_bom', 'int') > 0) { - print load_fiche_titre($langs->trans("ToConsume")); + print load_fiche_titre($langs->trans("ToConsume").' ('.$langs->trans("ForAQuantityOf1").')'); print '