diff --git a/htdocs/langs/en_US/mrp.lang b/htdocs/langs/en_US/mrp.lang
index b054df452d7..9a756ba3a79 100644
--- a/htdocs/langs/en_US/mrp.lang
+++ b/htdocs/langs/en_US/mrp.lang
@@ -66,3 +66,6 @@ AutoCloseMO=Close automatically the Manufacturing Order if quantities to consume
NoStockChangeOnServices=No stock change on services
ProductQtyToConsumeByMO=Product quantity still to consume by open MO
ProductQtyToProduceByMO=Product quentity still to produce by open MO
+AddNewConsumeLines=Add new line to consume
+ProductsToConsume=Products to consume
+ProductsToProduce=Products to produce
\ No newline at end of file
diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php
index e677c64efc0..bfbbf3d9a58 100644
--- a/htdocs/mrp/class/mo.class.php
+++ b/htdocs/mrp/class/mo.class.php
@@ -573,66 +573,69 @@ class Mo extends CommonObject
$this->db->begin();
// Insert lines in mrp_production table from BOM data
- if (!$error && $this->fk_bom > 0)
+ if (!$error)
{
// TODO Check that production has not started. If yes, we stop here.
+
$sql = 'DELETE FROM '.MAIN_DB_PREFIX.'mrp_production WHERE fk_mo = '.$this->id;
$this->db->query($sql);
- include_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
- $bom = new Bom($this->db);
- $bom->fetch($this->fk_bom);
- if ($bom->id > 0)
- {
- $moline = new MoLine($this->db);
+ $moline = new MoLine($this->db);
- // Line to produce
- $moline->fk_mo = $this->id;
- $moline->qty = $this->qty;
- $moline->fk_product = $this->fk_product;
- $moline->role = 'toproduce';
- $moline->position = 1;
+ // Line to produce
+ $moline->fk_mo = $this->id;
+ $moline->qty = $this->qty;
+ $moline->fk_product = $this->fk_product;
+ $moline->role = 'toproduce';
+ $moline->position = 1;
- $resultline = $moline->create($user, false); // Never use triggers here
- if ($resultline <= 0) {
- $error++;
- $this->error = $moline->error;
- $this->errors = $moline->errors;
- dol_print_error($this->db, $moline->error, $moline->errors);
- }
+ $resultline = $moline->create($user, false); // Never use triggers here
+ if ($resultline <= 0) {
+ $error++;
+ $this->error = $moline->error;
+ $this->errors = $moline->errors;
+ dol_print_error($this->db, $moline->error, $moline->errors);
+ }
- // Lines to consume
- if (! $error) {
- foreach ($bom->lines as $line)
- {
- $moline = new MoLine($this->db);
+ if ($this->fk_bom > 0) { // If a BOM is defined, we know what to consume.
+ include_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
+ $bom = new Bom($this->db);
+ $bom->fetch($this->fk_bom);
+ if ($bom->id > 0)
+ {
+ // Lines to consume
+ if (! $error) {
+ foreach ($bom->lines as $line)
+ {
+ $moline = new MoLine($this->db);
- $moline->fk_mo = $this->id;
- if ($line->qty_frozen) {
- $moline->qty = $line->qty; // Qty to consume does not depends on quantity to produce
- } else {
- $moline->qty = round($line->qty * $this->qty / $bom->efficiency, 2);
- }
- 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, false); // Never use triggers here
- if ($resultline <= 0) {
+ $moline->fk_mo = $this->id;
+ if ($line->qty_frozen) {
+ $moline->qty = $line->qty; // Qty to consume does not depends on quantity to produce
+ } else {
+ $moline->qty = round($line->qty * $this->qty / $bom->efficiency, 2);
+ }
+ if ($moline->qty <= 0) {
$error++;
- $this->error = $moline->error;
- $this->errors = $moline->errors;
- dol_print_error($this->db, $moline->error, $moline->errors);
+ $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, false); // Never use triggers here
+ if ($resultline <= 0) {
+ $error++;
+ $this->error = $moline->error;
+ $this->errors = $moline->errors;
+ dol_print_error($this->db, $moline->error, $moline->errors);
+ break;
+ }
+ }
}
}
}
@@ -1416,6 +1419,11 @@ class MoLine extends CommonObjectLine
*/
public function create(User $user, $notrigger = false)
{
+ if (empty($this->qty)) {
+ $this->error = 'BadValueForQty';
+ return -1;
+ }
+
return $this->createCommon($user, $notrigger);
}
diff --git a/htdocs/mrp/mo_card.php b/htdocs/mrp/mo_card.php
index 27cccab3d37..db05bfd408d 100644
--- a/htdocs/mrp/mo_card.php
+++ b/htdocs/mrp/mo_card.php
@@ -518,7 +518,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
print '';
print '
';
- print '| '.$langs->trans("ToProduce").' | ';
+ print ''.$langs->trans("ProductsToProduce").' | ';
print '';
if (!empty($object->lines))
{
diff --git a/htdocs/mrp/mo_production.php b/htdocs/mrp/mo_production.php
index e4d8361b721..32d2007141b 100644
--- a/htdocs/mrp/mo_production.php
+++ b/htdocs/mrp/mo_production.php
@@ -162,6 +162,25 @@ if (empty($reshook))
$result = $object->setStatut($object::STATUS_INPROGRESS, 0, '', 'MRP_REOPEN');
}
+ if ($action == 'confirm_addconsumeline' && GETPOST('addconsumelinebutton')) {
+ $moline = new MoLine($db);
+
+ // Line to produce
+ $moline->fk_mo = $object->id;
+ $moline->qty = GETPOST('qtytoadd', 'int');;
+ $moline->fk_product = GETPOST('productidtoadd', 'int');
+ $moline->role = 'toconsume';
+ $moline->position = 0;
+
+ $resultline = $moline->create($user, false); // Never use triggers here
+ if ($resultline <= 0) {
+ $error++;
+ setEventMessages($moline->error, $molines->errors, 'errors');
+ }
+
+ $action = '';
+ }
+
if (in_array($action, array('confirm_consumeorproduce', 'confirm_consumeandproduceall'))) {
$stockmove = new MouvementStock($db);
@@ -425,21 +444,43 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneMo', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
}
- // Confirmation of action xxxx
- if ($action == 'xxx')
+ // Confirmation of validation
+ if ($action == 'validate')
{
+ // We check that object has a temporary ref
+ $ref = substr($object->ref, 1, 4);
+ if ($ref == 'PROV') {
+ $object->fetch_product();
+ $numref = $object->getNextNumRef($object->fk_product);
+ } else {
+ $numref = $object->ref;
+ }
+
+ $text = $langs->trans('ConfirmValidateMo', $numref);
+ /*if (! empty($conf->notification->enabled))
+ {
+ require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
+ $notify = new Notify($db);
+ $text .= ' ';
+ $text .= $notify->confirmMessage('BOM_VALIDATE', $object->socid, $object);
+ }*/
+
$formquestion = array();
- /*
- $forcecombo=0;
- if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
- $formquestion = array(
- // 'text' => $langs->trans("ConfirmClone"),
- // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
- // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
- // array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1, 0, 0, '', 0, $forcecombo))
- );
- */
- $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('XXX'), $text, 'confirm_xxx', $formquestion, 0, 1, 220);
+ if (!empty($conf->mrp->enabled))
+ {
+ $langs->load("mrp");
+ require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
+ $formproduct = new FormProduct($db);
+ $forcecombo = 0;
+ if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
+ $formquestion = array(
+ // 'text' => $langs->trans("ConfirmClone"),
+ // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
+ // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
+ );
+ }
+
+ $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('Validate'), $text, 'confirm_validate', $formquestion, 0, 1, 220);
}
// Call Hook formConfirm
@@ -530,6 +571,23 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
// Note that $action and $object may be modified by hook
$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action);
if (empty($reshook)) {
+ // Validate
+ if ($object->status == $object::STATUS_DRAFT)
+ {
+ if ($permissiontoadd)
+ {
+ if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0))
+ {
+ print ''.$langs->trans("Validate").'';
+ }
+ else
+ {
+ $langs->load("errors");
+ print ''.$langs->trans("Validate").'';
+ }
+ }
+ }
+
// Consume or produce
if ($object->status == Mo::STATUS_VALIDATED || $object->status == Mo::STATUS_INPROGRESS) {
if ($permissiontoproduce) {
@@ -578,7 +636,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
print '';
}
- if (in_array($action, array('consumeorproduce', 'consumeandproduceall')))
+ if (in_array($action, array('consumeorproduce', 'consumeandproduceall', 'addconsumeline')))
{
print ' |