30require
'../main.inc.php';
31require_once DOL_DOCUMENT_ROOT.
'/bom/class/bom.class.php';
32require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formcompany.class.php';
33require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formfile.class.php';
34require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formprojet.class.php';
35require_once DOL_DOCUMENT_ROOT.
'/mrp/class/mo.class.php';
36require_once DOL_DOCUMENT_ROOT.
'/mrp/lib/mrp_mo.lib.php';
37require_once DOL_DOCUMENT_ROOT.
'/projet/class/project.class.php';
38require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
39require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
40require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
41require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/productlot.class.php';
42require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
43require_once DOL_DOCUMENT_ROOT.
'/workstation/class/workstation.class.php';
55$langs->loadLangs(array(
"mrp",
"stocks",
"other",
"product",
"productbatch"));
60$action =
GETPOST(
'action',
'aZ09');
61$confirm =
GETPOST(
'confirm',
'alpha');
62$cancel =
GETPOST(
'cancel',
'aZ09');
63$contextpage =
GETPOST(
'contextpage',
'aZ') ?
GETPOST(
'contextpage',
'aZ') :
'mocard';
64$backtopage =
GETPOST(
'backtopage',
'alpha');
67$fk_default_warehouse =
GETPOSTINT(
'fk_default_warehouse');
69$collapse =
GETPOST(
'collapse',
'aZ09comma');
74$diroutputmassaction =
$conf->mrp->dir_output.
'/temp/massgeneration/'.$user->id;
75$objectline =
new MoLine($db);
77$hookmanager->initHooks(array(
'moproduction',
'globalcard'));
80$extrafields->fetch_name_optionals_label(
$object->table_element);
82$search_array_options = $extrafields->getOptionalsFromPost(
$object->table_element,
'',
'search_');
85$search_all =
GETPOST(
"search_all",
'alpha');
87foreach (
$object->fields as $key => $val) {
88 if (
GETPOST(
'search_'.$key,
'alpha')) {
89 $search[$key] =
GETPOST(
'search_'.$key,
'alpha');
93if (empty($action) && empty($id) && empty($ref)) {
98include DOL_DOCUMENT_ROOT.
'/core/actions_fetchobject.inc.php';
103$isdraft = ((
$object->status == $object::STATUS_DRAFT) ? 1 : 0);
107$permissionnote = $user->hasRight(
'mrp',
'write');
108$permissiondellink = $user->hasRight(
'mrp',
'write');
109$permissiontoadd = $user->hasRight(
'mrp',
'write');
110$permissiontodelete = $user->hasRight(
'mrp',
'delete') || ($permissiontoadd && isset(
$object->status) &&
$object->status == $object::STATUS_DRAFT);
112$permissiontoproduce = $permissiontoadd;
113$permissiontoupdatecost = $user->hasRight(
'bom',
'read');
122$parameters = array();
123$reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
128if (empty($reshook)) {
131 $backurlforlist = DOL_URL_ROOT.
'/mrp/mo_list.php';
133 if (empty($backtopage) || ($cancel && empty($id))) {
135 if (empty($id) && (($action !=
'add' && $action !=
'create') || $cancel)) {
136 $backtopage = $backurlforlist;
138 $backtopage = DOL_URL_ROOT.
'/mrp/mo_production.php?id='.(
$id > 0 ?
$id :
'__ID__');
141 $triggermodname =
'MO_MODIFY';
143 if ($action ==
'confirm_cancel' && $confirm ==
'yes' && !empty($permissiontoadd)) {
144 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
145 $result =
$object->cancel($user, 0, $also_cancel_consumed_and_produced_lines);
147 header(
"Location: " . DOL_URL_ROOT.
'/mrp/mo_card.php?id=' .
$object->id);
153 } elseif ($action ==
'confirm_delete' && $confirm ==
'yes' && !empty($permissiontodelete)) {
154 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
155 $result =
$object->delete($user, 0, $also_cancel_consumed_and_produced_lines);
157 header(
"Location: " . $backurlforlist);
166 include DOL_DOCUMENT_ROOT.
'/core/actions_addupdatedelete.inc.php';
169 include DOL_DOCUMENT_ROOT.
'/core/actions_dellink.inc.php';
172 include DOL_DOCUMENT_ROOT.
'/core/actions_printing.inc.php';
175 $triggersendname =
'MO_SENTBYMAIL';
176 $autocopy =
'MAIN_MAIL_AUTOCOPY_MO_TO';
177 $trackid =
'mo'.$object->id;
178 include DOL_DOCUMENT_ROOT.
'/core/actions_sendmails.inc.php';
183 if ($action ==
'set_thirdparty' && $permissiontoadd) {
184 $object->setValueFrom(
'fk_soc',
GETPOSTINT(
'fk_soc'),
'',
null,
'date',
'', $user, $triggermodname);
186 if ($action ==
'classin' && $permissiontoadd) {
190 if ($action ==
'confirm_reopen' && $permissiontoadd) {
191 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_REOPEN');
194 if (($action ==
'confirm_addconsumeline' &&
GETPOST(
'addconsumelinebutton') && $permissiontoadd)
195 || ($action ==
'confirm_addproduceline' &&
GETPOST(
'addproducelinebutton') && $permissiontoadd)) {
196 $moline =
new MoLine($db);
201 $moline->fk_product =
GETPOSTINT(
'productidtoadd');
202 if (
GETPOST(
'addconsumelinebutton')) {
203 $moline->role =
'toconsume';
205 $moline->role =
'toproduce';
207 $moline->origin_type =
'free';
208 $moline->position = 0;
211 if (!empty($moline->fk_product)) {
212 $tmpproduct =
new Product($db);
213 $tmpproduct->fetch($moline->fk_product);
215 $moline->fk_default_workstation = $tmpproduct->fk_default_workstation;
219 $moline->fk_unit = $tmpproduct->fk_unit;
223 $extralabelsline = $extrafields->fetch_name_optionals_label(
$object->table_element_line);
224 $array_options = $extrafields->getOptionalsFromPost(
$object->table_element_line);
226 if (is_array($extralabelsline)) {
228 foreach ($extralabelsline as $key => $value) {
229 unset($_POST[
"options_".$key]);
232 if (is_array($array_options) && count($array_options) > 0) {
233 $moline->array_options = $array_options;
236 $resultline = $moline->create($user,
false);
237 if ($resultline <= 0) {
244 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
248 if (in_array($action, array(
'confirm_consumeorproduce',
'confirm_consumeandproduceall')) && $permissiontoproduce) {
251 $labelmovement =
GETPOST(
'inventorylabel',
'alphanohtml');
252 $codemovement =
GETPOST(
'inventorycode',
'alphanohtml');
257 foreach (
$object->lines as $line) {
258 if ($line->role ==
'toconsume') {
259 $tmpproduct =
new Product($db);
260 $tmpproduct->fetch($line->fk_product);
263 while (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
266 if ($qtytoprocess != 0) {
268 if (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i)) {
269 if (!(
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0)) {
270 $langs->load(
"errors");
271 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
274 if ($tmpproduct->status_batch && (!
GETPOST(
'batch-'.$line->id.
'-'.$i))) {
275 $langs->load(
"errors");
276 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
282 if (!$error &&
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0) {
284 $id_product_batch = 0;
286 $stockmove->context[
'mrp_role'] =
'toconsume';
288 if ($qtytoprocess >= 0) {
289 $idstockmove = $stockmove->livraison($user, $line->fk_product,
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i), $qtytoprocess, 0, $labelmovement,
dol_now(),
'',
'',
GETPOST(
'batch-'.$line->id.
'-'.$i), $id_product_batch, $codemovement);
291 $idstockmove = $stockmove->reception($user, $line->fk_product,
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i), $qtytoprocess * -1, 0, $labelmovement,
dol_now(),
'',
'',
GETPOST(
'batch-'.$line->id.
'-'.$i), $id_product_batch, $codemovement);
293 if ($idstockmove < 0) {
301 $moline =
new MoLine($db);
303 $moline->position = $pos;
304 $moline->fk_product = $line->fk_product;
305 $moline->fk_warehouse =
GETPOSTINT(
'idwarehouse-'.$line->id.
'-'.$i);
306 $moline->qty = $qtytoprocess;
307 $moline->batch =
GETPOST(
'batch-'.$line->id.
'-'.$i);
308 $moline->role =
'consumed';
309 $moline->fk_mrp_production = $line->id;
310 $moline->fk_stock_movement = $idstockmove == 0 ? null : $idstockmove;
311 $moline->fk_user_creat = $user->id;
313 $resultmoline = $moline->create($user);
314 if ($resultmoline <= 0) {
331 foreach (
$object->lines as $line) {
332 if ($line->role ==
'toproduce') {
333 $tmpproduct =
new Product($db);
334 $tmpproduct->fetch($line->fk_product);
337 while (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
338 $qtytoprocess = (float)
price2num(
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i));
339 $pricetoprocess =
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) ?
price2num(
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i)) : 0;
341 if ($qtytoprocess != 0) {
343 if (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i)) {
344 if (!(
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0)) {
345 $langs->load(
"errors");
346 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
349 if (isModEnabled(
'productbatch') && $tmpproduct->status_batch && (!
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i))) {
350 $langs->load(
"errors");
351 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
357 if (!$error &&
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0) {
359 $id_product_batch = 0;
360 $stockmove->origin_type =
$object->element;
361 $stockmove->origin_id =
$object->id;
362 $stockmove->context[
'mrp_role'] =
'toproduce';
364 $idstockmove = $stockmove->reception($user, $line->fk_product,
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i), $qtytoprocess, $pricetoprocess, $labelmovement,
'',
'',
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i),
dol_now(), $id_product_batch, $codemovement);
365 if ($idstockmove < 0) {
373 $moline =
new MoLine($db);
375 $moline->position = $pos;
376 $moline->fk_product = $line->fk_product;
377 $moline->fk_warehouse =
GETPOSTINT(
'idwarehousetoproduce-'.$line->id.
'-'.$i);
378 $moline->qty = $qtytoprocess;
379 $moline->batch =
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i);
380 $moline->role =
'produced';
381 $moline->fk_mrp_production = $line->id;
382 $moline->fk_stock_movement = $idstockmove;
383 $moline->fk_user_creat = $user->id;
385 $resultmoline = $moline->create($user);
386 if ($resultmoline <= 0) {
401 $consumptioncomplete =
true;
402 $productioncomplete =
true;
405 foreach (
$object->lines as $line) {
406 if ($line->role ==
'toconsume') {
407 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
408 $alreadyconsumed = 0;
409 foreach ($arrayoflines as $line2) {
410 $alreadyconsumed += $line2[
'qty'];
413 if ($alreadyconsumed < $line->qty) {
414 $consumptioncomplete =
false;
417 if ($line->role ==
'toproduce') {
418 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
419 $alreadyproduced = 0;
420 foreach ($arrayoflines as $line2) {
421 $alreadyproduced += $line2[
'qty'];
424 if ($alreadyproduced < $line->qty) {
425 $productioncomplete =
false;
430 $consumptioncomplete =
false;
431 $productioncomplete =
false;
435 dol_syslog(
"consumptioncomplete = ".json_encode($consumptioncomplete).
" productioncomplete = ".json_encode($productioncomplete));
436 if ($consumptioncomplete && $productioncomplete) {
437 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
439 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_MO_PRODUCED');
448 $action = str_replace(
'confirm_',
'', $action);
454 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
460 if ($action ==
'confirm_produced' && $confirm ==
'yes' && $permissiontoadd) {
461 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
465 $outputlangs = $langs;
468 $newlang =
GETPOST(
'lang_id',
'aZ09');
471 $newlang =
$object->thirdparty->default_lang;
473 if (!empty($newlang)) {
475 $outputlangs->setDefaultLang($newlang);
480 $object->generateDocument($model, $outputlangs, 0, 0, 0);
487 if ($action ==
'confirm_editline' && $permissiontoadd) {
488 $moline =
new MoLine($db);
491 $extrafields->fetch_name_optionals_label($moline->element);
492 foreach ($extrafields->attributes[$moline->table_element][
'label'] as $key => $label) {
493 $value =
GETPOST(
'options_'.$key,
'alphanohtml');
494 $moline->array_options[
"options_".$key] = $value;
497 $res = $moline->update($user);
500 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
503 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
515$form =
new Form($db);
522$title = $langs->trans(
'Mo');
523$help_url =
'EN:Module_Manufacturing_Orders|FR:Module_Ordres_de_Fabrication|DE:Modul_Fertigungsauftrag';
524$morejs = array(
'/mrp/js/lib_dispatch.js.php');
525llxHeader(
'', $title, $help_url,
'', 0, 0, $morejs,
'',
'',
'mod-mrp page-card_production');
530if (
$object->id > 0 && (empty($action) || ($action !=
'edit' && $action !=
'create'))) {
531 $res =
$object->fetch_thirdparty();
532 $res =
$object->fetch_optionals();
535 $tmpwarehouse->fetch(
$object->fk_warehouse);
536 $fk_default_warehouse =
$object->fk_warehouse;
546 if ($action ==
'delete') {
547 $formquestion = array(
549 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
550 'name' =>
'alsoCancelConsumedAndProducedLines',
551 'type' =>
'checkbox',
555 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'DeleteMo'), $langs->trans(
'ConfirmDeleteMo'),
'confirm_delete', $formquestion, 0, 1);
558 if ($action ==
'deleteline') {
559 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&lineid='.$lineid.
'&fk_movement='.$fk_movement, $langs->trans(
'DeleteLine'), $langs->trans(
'ConfirmDeleteLine'),
'confirm_deleteline',
'', 0, 1);
562 if ($action ==
'clone') {
564 $formquestion = array();
565 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'ToClone'), $langs->trans(
'ConfirmCloneMo',
$object->ref),
'confirm_clone', $formquestion,
'yes', 1);
569 if ($action ==
'validate') {
571 $ref = substr(
$object->ref, 1, 4);
572 if ($ref ==
'PROV') {
579 $text = $langs->trans(
'ConfirmValidateMo', $numref);
588 $formquestion = array();
589 if (isModEnabled(
'mrp')) {
591 require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
594 if (
$conf->browser->name ==
'ie') {
597 $formquestion = array(
604 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'Validate'), $text,
'confirm_validate', $formquestion, 0, 1, 220);
608 if ($action ==
'cancel') {
609 $formquestion = array(
611 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
612 'name' =>
'alsoCancelConsumedAndProducedLines',
613 'type' =>
'checkbox',
614 'value' => !
getDolGlobalString(
'MO_ALSO_CANCEL_CONSUMED_AND_PRODUCED_LINES_BY_DEFAULT') ? 0 : 1
617 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"] .
'?id=' .
$object->id, $langs->trans(
'CancelMo'), $langs->trans(
'ConfirmCancelMo'),
'confirm_cancel', $formquestion, 0, 1);
621 $parameters = array(
'formConfirm' => $formconfirm,
'lineid' => $lineid);
622 $reshook = $hookmanager->executeHooks(
'formConfirm', $parameters, $object, $action);
623 if (empty($reshook)) {
624 $formconfirm .= $hookmanager->resPrint;
625 } elseif ($reshook > 0) {
626 $formconfirm = $hookmanager->resPrint;
635 $linkback =
'<a href="'.DOL_URL_ROOT.
'/mrp/mo_list.php?restore_lastsearch_values=1'.(!empty($socid) ?
'&socid='.$socid :
'').
'">'.$langs->trans(
"BackToList").
'</a>';
637 $morehtmlref =
'<div class="refidno">';
646 if (is_object(
$object->thirdparty)) {
647 $morehtmlref .=
$object->thirdparty->getNomUrl(1,
'customer');
649 $morehtmlref .=
' (<a href="'.DOL_URL_ROOT.
'/commande/list.php?socid='.
$object->thirdparty->id.
'&search_societe='.urlencode(
$object->thirdparty->name).
'">'.$langs->trans(
"OtherOrders").
'</a>)';
654 if (isModEnabled(
'project')) {
655 $langs->load(
"projects");
656 if (is_object(
$object->thirdparty)) {
657 $morehtmlref .=
'<br>';
659 if ($permissiontoadd) {
660 $morehtmlref .=
img_picto($langs->trans(
"Project"),
'project',
'class="pictofixedwidth"');
661 if ($action !=
'classify') {
662 $morehtmlref .=
'<a class="editfielda" href="'.$_SERVER[
'PHP_SELF'].
'?action=classify&token='.
newToken().
'&id='.
$object->id.
'">'.
img_edit($langs->transnoentitiesnoconv(
'SetProject')).
'</a> ';
664 $morehtmlref .= $form->form_project($_SERVER[
'PHP_SELF'].
'?id='.
$object->id,
$object->socid,
$object->fk_project, ($action ==
'classify' ?
'projectid' :
'none'), 0, 0, 0, 1,
'',
'maxwidth300');
666 if (!empty(
$object->fk_project)) {
668 $proj->fetch(
$object->fk_project);
669 $morehtmlref .= $proj->getNomUrl(1);
671 $morehtmlref .=
'<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).
'</span>';
676 $morehtmlref .=
'</div>';
679 dol_banner_tab($object,
'ref', $linkback, 1,
'ref',
'ref', $morehtmlref);
682 print
'<div class="fichecenter">';
683 print
'<div class="fichehalfleft">';
684 print
'<div class="underbanner clearboth"></div>';
685 print
'<table class="border centpercent tableforfield">'.
"\n";
688 $keyforbreak =
'fk_warehouse';
689 unset(
$object->fields[
'fk_project']);
690 unset(
$object->fields[
'fk_soc']);
691 include DOL_DOCUMENT_ROOT.
'/core/tpl/commonfields_view.tpl.php';
694 include DOL_DOCUMENT_ROOT.
'/core/tpl/extrafields_view.tpl.php';
700 print
'<div class="clearboth"></div>';
705 if (!in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
706 print
'<div class="tabsAction">';
708 $parameters = array();
710 $reshook = $hookmanager->executeHooks(
'addMoreActionsButtons', $parameters, $object, $action);
711 if (empty($reshook)) {
713 if (
$object->status == $object::STATUS_DRAFT) {
714 if ($permissiontoadd) {
716 print
'<a class="butAction" href="'.$_SERVER[
'PHP_SELF'].
'?id='.
$object->id.
'&action=validate&token='.$newToken.
'">'.$langs->trans(
"Validate").
'</a>';
718 $langs->load(
"errors");
719 print
'<a class="butActionRefused" href="" title="'.$langs->trans(
"ErrorAddAtLeastOneLineFirst").
'">'.$langs->trans(
"Validate").
'</a>';
725 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
726 if ($permissiontoproduce) {
727 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeorproduce&token='.$newToken.
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
729 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
731 } elseif (
$object->status == Mo::STATUS_DRAFT) {
732 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
736 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
737 if ($permissiontoproduce) {
738 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeandproduceall&token='.$newToken.
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
740 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
742 } elseif (
$object->status == Mo::STATUS_DRAFT) {
743 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
747 if ($permissiontoadd) {
748 if (
$object->status == $object::STATUS_VALIDATED ||
$object->status == $object::STATUS_INPROGRESS) {
749 $arrayproduced =
$object->fetchLinesLinked(
'produced', 0);
751 foreach ($arrayproduced as $lineproduced) {
752 $nbProduced += $lineproduced[
'qty'];
754 if ($nbProduced > 0) {
755 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_produced&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
757 print
'<a class="butActionRefused" href="#" title="'.$langs->trans(
"GoOnTabProductionToProduceFirst", $langs->transnoentitiesnoconv(
"Production")).
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
760 print
'<a class="butActionDelete" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=cancel&token='.$newToken.
'">'.$langs->trans(
"Cancel").
'</a>'.
"\n";
763 if (
$object->status == $object::STATUS_CANCELED) {
764 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"ReOpen").
'</a>'.
"\n";
767 if (
$object->status == $object::STATUS_PRODUCED) {
768 if ($permissiontoproduce) {
769 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&token='.$newToken.
'">'.$langs->trans(
'ReOpen').
'</a>';
771 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ReOpen').
'</a>';
780 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline',
'addproduceline',
'editline'))) {
781 print
'<form method="POST" action="'.$_SERVER[
"PHP_SELF"].
'">';
782 print
'<input type="hidden" name="token" value="'.newToken().
'">';
783 print
'<input type="hidden" name="action" value="confirm_'.$action.
'">';
784 print
'<input type="hidden" name="backtopage" value="'.$backtopage.
'">';
785 print
'<input type="hidden" name="id" value="'.$id.
'">';
788 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
789 $defaultstockmovementlabel =
GETPOST(
'inventorylabel',
'alphanohtml') ?
GETPOST(
'inventorylabel',
'alphanohtml') : $langs->trans(
"ProductionForRef",
$object->
ref);
792 print
'<div class="center'.(in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) ?
' formconsumeproduce' :
'').
'">';
793 print
'<div class="opacitymedium hideonsmartphone paddingbottom">'.$langs->trans(
"ConfirmProductionDesc", $langs->transnoentitiesnoconv(
"Confirm")).
'<br></div>';
794 print
'<span class="fieldrequired">'.$langs->trans(
"InventoryCode").
':</span> <input type="text" class="minwidth150 maxwidth200" name="inventorycode" value="'.$defaultstockmovementcode.
'"> ';
795 print
'<span class="clearbothonsmartphone"></span>';
796 print $langs->trans(
"MovementLabel").
': <input type="text" class="minwidth300" name="inventorylabel" value="'.$defaultstockmovementlabel.
'"><br><br>';
797 print
'<input type="checkbox" id="autoclose" name="autoclose" value="1"'.(GETPOSTISSET(
'inventorylabel') ? (
GETPOST(
'autoclose') ?
' checked="checked"' :
'') :
' checked="checked"').
'> <label for="autoclose">'.$langs->trans(
"AutoCloseMO").
'</label><br>';
798 print
'<input type="submit" class="button" value="'.$langs->trans(
"Confirm").
'" name="confirm">';
800 print
'<input class="button button-cancel" type="submit" value="'.$langs->trans(
"Cancel").
'" name="cancel">';
814 if (!empty(
$object->table_element_line)) {
821 $res = $bom->fetch(
$object->fk_bom);
823 $bom->calculateCosts();
824 $bomcost = $bom->unit_cost;
830 print
'<!-- Lines to consume -->'.
"\n";
831 print
'<div class="fichecenter">';
832 print
'<div class="fichehalfleft">';
833 print
'<div class="clearboth"></div>';
835 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addconsumeline&token='.
newToken();
836 $permissiontoaddaconsumeline = (
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED) ? 1 : -2;
837 $parameters = array(
'morecss' =>
'reposition');
839 if ($permissiontoaddaconsumeline == -2) {
840 $helpText = $langs->trans(
'MOIsClosed');
844 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
845 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewConsumeLines'), $helpText,
'fa fa-plus-circle size15x', $url,
'', $permissiontoaddaconsumeline, $parameters);
848 print
load_fiche_titre($langs->trans(
'Consumption'), $newcardbutton,
'', 0,
'',
'',
'');
850 print
'<div class="div-table-responsive-no-min">';
851 print
'<table class="noborder noshadow centpercent nobottom">';
853 print
'<!-- Line of title for products to consume -->'.
"\n";
854 print
'<tr class="liste_titre">';
856 print
'<td>'.$langs->trans(
"Product").
'</td>';
858 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
863 print
'<td class="right">'.$langs->trans(
"UnitCost").
'</td>';
866 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyConsumedShort"), $langs->trans(
"QtyAlreadyConsumed")).
'</td>';
869 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
870 print $langs->trans(
"Warehouse");
871 if (isModEnabled(
'workstation')) {
872 print
' '.$langs->trans(
"or").
' '.$langs->trans(
"Workstation");
875 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
876 $listwarehouses = $tmpwarehouse->list_array(1);
877 if (count($listwarehouses) > 1) {
878 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, $langs->trans(
"ForceTo"), 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
879 } elseif (count($listwarehouses) == 1) {
880 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
886 if (isModEnabled(
'stock')) {
888 print
'<td align="right">';
889 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
890 print $langs->trans(
"Stock");
895 if (isModEnabled(
'productbatch')) {
897 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
898 print $langs->trans(
"Batch");
910 if (
$object->status == Mo::STATUS_DRAFT) {
915 if ($permissiontodelete) {
921 if ($action ==
'addconsumeline') {
922 print
'<!-- Add line to consume -->'.
"\n";
923 print
'<tr class="liste_titre">';
926 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth150');
929 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width40 right"></td>';
938 if (isModEnabled(
'stock')) {
941 if (isModEnabled(
'productbatch')) {
945 print
'<td colspan="'.$colspan.
'">';
946 print
'<input type="submit" class="button buttongen button-add" name="addconsumelinebutton" value="'.$langs->trans(
"Add").
'">';
947 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdconsumelinebutton" value="'.$langs->trans(
"Cancel").
'">';
952 if (
$object->status == Mo::STATUS_DRAFT) {
956 if ($permissiontodelete) {
962 if (is_object($objectline)) {
963 $extrafields->fetch_name_optionals_label(
$object->table_element_line);
964 $temps = $objectline->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
965 if (!empty($temps)) {
966 print
'<tr class="liste_titre"><td style="padding-top: 20px" colspan="9" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
978 $nblinetoconsume = 0;
979 foreach (
$object->lines as $line) {
980 if ($line->role ==
'toconsume') {
985 $nblinetoconsumecursor = 0;
986 foreach (
$object->lines as $line) {
987 if ($line->role ==
'toconsume') {
988 $nblinetoconsumecursor++;
990 $tmpproduct =
new Product($db);
991 $tmpproduct->fetch($line->fk_product);
992 $linecost =
price2num($tmpproduct->pmp,
'MT');
996 $costprice =
price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp);
997 if (empty($costprice)) {
998 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1000 if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) {
1001 $costprice = $productFournisseur->fourn_unitprice;
1009 if ($useunit && $line->fk_unit > 0) {
1011 $qtyhourservice = 0;
1012 if (preg_match(
'/^(\d+)([a-z]+)$/', $tmpproduct->duration, $reg)) {
1015 $qtyhourforline = 0;
1016 if ($line->fk_unit) {
1021 if ($qtyhourservice && $qtyhourforline) {
1022 $linecost =
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MT');
1023 $bomcostupdated +=
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MU');
1026 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1030 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1034 $bomcostupdated =
price2num($bomcostupdated,
'MU');
1035 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1036 $alreadyconsumed = 0;
1037 foreach ($arrayoflines as $line2) {
1038 $alreadyconsumed += $line2[
'qty'];
1041 if ($action ==
'editline' && $lineid == $line->id) {
1042 $linecost =
price2num($tmpproduct->pmp,
'MT');
1044 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1045 $alreadyconsumed = 0;
1046 if (is_array($arrayoflines) && !empty($arrayoflines)) {
1047 foreach ($arrayoflines as $line2) {
1048 $alreadyconsumed += $line2[
'qty'];
1051 $suffix =
'_' . $line->id;
1052 print
'<!-- Line to dispatch ' . $suffix .
' (line edited) -->' .
"\n";
1054 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1056 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1058 print
'<input name="lineid" type="hidden" value="' . $line->id .
'">';
1061 print
'<td>' . $tmpproduct->getNomUrl(1);
1062 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</span>';
1066 print
'<td class="right nowraponall">';
1067 print
'<input class="width40 right" name="qty_lineProduce" value="'. $line->qty.
'">';
1071 print
'<td class="right nowraponall">';
1079 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1084 print
'<td class="right">';
1085 print
' ' .
price2num($alreadyconsumed,
'MS');
1093 if (isModEnabled(
'stock')) {
1094 print
'<td class="nowraponall right">';
1095 if ($tmpproduct->isStockManaged()) {
1096 if ($tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1097 print
img_warning($langs->trans(
'StockTooLow')).
' ';
1099 print
'<span class="left">'. $tmpproduct->stock_reel .
' </span>';
1105 if (isModEnabled(
'productbatch')) {
1109 print
'<td colspan="'.(3 + (
$object->status == Mo::STATUS_DRAFT ? 1 : 0) + ($permissiontodelete ? 1 : 0)).
'">';
1110 print
'<input type="submit" class="button buttongen button-add small nominwidth" name="save" value="' . $langs->trans(
"Save") .
'">';
1111 print
'<input type="submit" class="button buttongen button-cancel small nominwidth" name="cancel" value="' . $langs->trans(
"Cancel") .
'">';
1117 if (!empty($extrafields)) {
1118 $line->fetch_optionals();
1119 $temps = $line->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
1120 if (!empty($temps)) {
1122 print
'<tr><td colspan="'.$colspan.
'"><div style="padding-top: 20px" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
1124 print
'</div></td></tr>';
1128 $suffix =
'_' . $line->id;
1129 print
'<!-- Line to dispatch ' . $suffix .
' -->' .
"\n";
1131 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1132 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1134 print
'<tr data-line-id="' . $line->id .
'">';
1137 print
'<td>' . $tmpproduct->getNomUrl(1);
1138 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</div>';
1142 print
'<td class="right nowraponall">';
1144 if ($line->qty_frozen) {
1145 $help = ($help ?
'<br>' :
'') .
'<strong>' . $langs->trans(
"QuantityFrozen") .
'</strong>: ' .
yn(1) .
' (' . $langs->trans(
"QuantityConsumedInvariable") .
')';
1146 print $form->textwithpicto(
'', $help, -1,
'lock') .
' ';
1148 if ($line->disable_stock_change) {
1149 $help = ($help ?
'<br>' :
'') .
'<strong>' . $langs->trans(
"DisableStockChange") .
'</strong>: ' .
yn(1) .
' (' . (($tmpproduct->type ==
Product::TYPE_SERVICE && !
getDolGlobalString(
'STOCK_SUPPORTS_SERVICES')) ? $langs->trans(
"NoStockChangeOnServices") : $langs->trans(
"DisableStockChangeHelp")) .
')';
1150 print $form->textwithpicto(
'', $help, -1,
'help') .
' ';
1156 print
'<td class="right nowraponall">';
1164 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1165 print
'<td class="right nowraponall">';
1166 print
price($linecost);
1171 print
'<td class="right">';
1172 if ($alreadyconsumed) {
1174 print
'jQuery(document).ready(function() {
1175 jQuery("#expandtoproduce' . $line->id .
'").click(function() {
1176 console.log("Expand mrp_production line ' . $line->id .
'");
1177 jQuery(".expanddetail' . $line->id .
'").toggle();';
1178 if ($nblinetoconsume == $nblinetoconsumecursor) {
1179 print
'if (jQuery("#tablelines").hasClass("nobottom")) { jQuery("#tablelines").removeClass("nobottom"); } else { jQuery("#tablelines").addClass("nobottom"); }';
1185 if (empty(
$conf->use_javascript_ajax)) {
1186 print
'<a href="' . $_SERVER[
"PHP_SELF"] .
'?collapse=' . $collapse .
',' . $line->id .
'">';
1188 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce' . $line->id .
'"');
1189 if (empty(
$conf->use_javascript_ajax)) {
1193 if ($nblinetoconsume == $nblinetoconsumecursor) {
1194 print
'<script>jQuery("#tablelines").removeClass("nobottom");</script>';
1197 print
' ' .
price2num($alreadyconsumed,
'MS');
1202 if (
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') && $tmpwarehouse->id > 0) {
1203 print
img_picto(
'', $tmpwarehouse->picto) .
" " . $tmpwarehouse->label;
1205 if (isModEnabled(
'workstation') && $line->fk_default_workstation > 0) {
1207 $tmpworkstation->fetch($line->fk_default_workstation);
1208 print $tmpworkstation->getNomUrl(1);
1213 if (isModEnabled(
'stock')) {
1214 print
'<td class="nowraponall right">';
1216 if (!$line->disable_stock_change && $tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1217 print
img_warning($langs->trans(
'StockTooLow')) .
' ';
1219 if (!
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') || empty($tmpwarehouse->id)) {
1220 print
price2num($tmpproduct->stock_reel,
'MS');
1223 $tmpproduct->load_stock();
1224 $wh_stock = $tmpproduct->stock_warehouse[$tmpwarehouse->id];
1225 if (!empty($wh_stock)) {
1236 if (isModEnabled(
'productbatch')) {
1247 if (
$object->status == Mo::STATUS_DRAFT) {
1248 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1249 print
'<td class="center">';
1250 print
'<a class="reposition editfielda" href="' . $href .
'">';
1251 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1257 if ($permissiontodelete) {
1258 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=deleteline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1259 print
'<td class="center">';
1260 print
'<a class="reposition" href="' . $href .
'">';
1261 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1269 if (!empty($extrafields)) {
1270 $line->fetch_optionals();
1271 $temps = $line->showOptionals($extrafields,
'view', array(),
'',
'', 1,
'line');
1272 if (!empty($temps)) {
1274 print
'<tr><td colspan="'.$colspan.
'"><div id="extrafield_lines_area_'.$line->id.
'" name="extrafield_lines_area_'.$line->id.
'">';
1276 print
'</div></td></tr>';
1282 foreach ($arrayoflines as $line2) {
1283 print
'<tr class="expanddetail'.$line->id.
' hideobject opacitylow">';
1287 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1288 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1299 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1304 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1307 print
'<td class="tdoverflowmax150">';
1308 if ($line2[
'fk_warehouse'] > 0) {
1309 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1311 print $tmpwarehouse->getNomUrl(1);
1317 if (isModEnabled(
'stock')) {
1322 if (isModEnabled(
'productbatch')) {
1324 if ($line2[
'batch'] !=
'') {
1325 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1326 print $tmpbatch->getNomUrl(1);
1338 if (
$object->status == Mo::STATUS_DRAFT) {
1339 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line2[
'rowid']);
1340 print
'<td class="center">';
1341 print
'<a class="reposition" href="' . $href .
'">';
1342 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1348 if ($permissiontodelete) {
1349 $href = $_SERVER[
"PHP_SELF"].
'?id='.((int)
$object->id).
'&action=deleteline&token='.
newToken().
'&lineid='.((int) $line2[
'rowid']).
'&fk_movement='.((int) $line2[
'fk_stock_movement']);
1350 print
'<td class="center">';
1351 print
'<a class="reposition" href="'.$href.
'">';
1352 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1360 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1362 print
'<!-- Enter line to consume -->'.
"\n";
1364 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1366 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToConsume").
'</span></td>';
1367 $preselected = (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i) ?
GETPOST(
'qty-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyconsumed));
1368 if ($action ==
'consumeorproduce' && !
getDolGlobalString(
'MRP_AUTO_SET_REMAINING_QUANTITIES_TO_BE_CONSUMED') && !GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
1373 if (
getDolGlobalString(
'MRP_NEVER_CONSUME_MORE_THAN_EXPECTED') && ($line->qty - $alreadyconsumed) <= 0) {
1374 $disable =
'disabled';
1378 print
'<input type="hidden" name="product-'.$line->id.
'-'.$i.
'" value="'.$line->fk_product.
'">';
1381 print
'<td class="right"><input type="text" class="width50 right" id="qtytoconsume-' . $line->id .
'-' . $i .
'" name="qty-' . $line->id .
'-' . $i .
'" value="' . $preselected .
'" ' . $disable .
'></td>';
1387 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1397 if (empty($line->disable_stock_change)) {
1398 $preselected = (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) : ($tmpproduct->fk_default_warehouse > 0 ? $tmpproduct->fk_default_warehouse :
'ifone'));
1399 print $formproduct->selectWarehouses($preselected,
'idwarehouse-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0, array(),
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1401 print
'<span class="opacitymedium">'.$langs->trans(
"DisableStockChange").
'</span>';
1404 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1409 if (isModEnabled(
'stock')) {
1414 if (isModEnabled(
'productbatch')) {
1415 print
'<td class="nowraponall">';
1416 if ($tmpproduct->status_batch) {
1417 $preselected = (GETPOSTISSET(
'batch-'.$line->id.
'-'.$i) ?
GETPOST(
'batch-'.$line->id.
'-'.$i) :
'');
1418 print
'<input type="text" class="width75" name="batch-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'" list="batch-'.$line->id.
'-'.$i.
'">';
1419 print $formproduct->selectLotDataList(
'batch-'.$line->id.
'-'.$i, 0, $line->fk_product, 0, array());
1426 print
'<td align="right" class="split">';
1427 print
' '.img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.((int) $line->id).
', \''.
dol_escape_js($type).
'\', \
'qtymissingconsume\')"');
1431 print
'<td align="right" class="splitall">';
1432 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1433 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" data-max-qty="1" onClick="addDispatchLine('.$line->id.
', \'batch\', \'allmissingconsume\')"');
1438 if (
$object->status == Mo::STATUS_DRAFT) {
1443 if ($permissiontodelete) {
1457 print
'<script type="text/javascript">
1458 $(document).ready(function () {
1459 $("select[name=fk_default_warehouse]").change(function() {
1460 var fk_default_warehouse = $("option:selected", this).val();
1461 $("select[name^=idwarehouse-]").val(fk_default_warehouse).change();
1466 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) &&
1468 print
'<script>$(document).ready(function () {
1469 $("#fk_default_warehouse").change();
1477 print
'<div class="fichehalfright">';
1478 print
'<div class="clearboth"></div>';
1480 $nblinetoproduce = 0;
1481 foreach (
$object->lines as $line) {
1482 if ($line->role ==
'toproduce') {
1487 $newcardbutton =
'';
1488 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addproduceline&token='.
newToken();
1489 $permissiontoaddaproductline =
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED;
1490 $parameters = array(
'morecss' =>
'reposition');
1491 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
1492 if ($nblinetoproduce == 0 ||
$object->mrptype == 1) {
1493 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewProduceLines'),
'',
'fa fa-plus-circle size15x', $url,
'', (
int) $permissiontoaddaproductline, $parameters);
1497 print
load_fiche_titre($langs->trans(
'Production'), $newcardbutton,
'', 0,
'',
'');
1499 print
'<div class="div-table-responsive-no-min">';
1500 print
'<table id="tablelinestoproduce" class="noborder noshadow nobottom centpercent">';
1502 print
'<tr class="liste_titre">';
1504 print
'<td>'.$langs->trans(
"Product").
'</td>';
1506 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
1509 print
'<td class="right">'.$langs->trans(
"Unit").
'</td>';
1512 if ($permissiontoupdatecost) {
1513 if (empty($bomcostupdated)) {
1514 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"UnitCost"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1516 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"ManufacturingPrice"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1520 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyProducedShort"), $langs->trans(
"QtyAlreadyProduced")).
'</td>';
1523 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1524 print $langs->trans(
"Warehouse");
1529 if (isModEnabled(
'productbatch')) {
1531 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1532 print $langs->trans(
"Batch");
1544 if ($permissiontodelete) {
1550 if ($action ==
'addproduceline') {
1551 print
'<!-- Add line to produce -->'.
"\n";
1552 print
'<tr class="liste_titre">';
1556 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
1559 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
1565 if ($permissiontoupdatecost) {
1569 print
'<td colspan="2">';
1570 print
'<input type="submit" class="button buttongen button-add" name="addproducelinebutton" value="'.$langs->trans(
"Add").
'">';
1571 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdproducelinebutton" value="'.$langs->trans(
"Cancel").
'">';
1574 if (isModEnabled(
'productbatch')) {
1584 if ($permissiontodelete) {
1591 $nblinetoproduce = 0;
1592 foreach (
$object->lines as $line) {
1593 if ($line->role ==
'toproduce') {
1598 $nblinetoproducecursor = 0;
1599 foreach (
$object->lines as $line) {
1600 if ($line->role ==
'toproduce') {
1603 $nblinetoproducecursor++;
1605 $tmpproduct =
new Product($db);
1606 $tmpproduct->fetch($line->fk_product);
1608 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
1609 $alreadyproduced = 0;
1610 foreach ($arrayoflines as $line2) {
1611 $alreadyproduced += $line2[
'qty'];
1614 $suffix =
'_'.$line->id;
1615 print
'<!-- Line to dispatch '.$suffix.
' (toproduce) -->'.
"\n";
1617 print
'<input id="qty_ordered'.$suffix.
'" type="hidden" value="'.$line->qty.
'">';
1618 print
'<input id="qty_dispatched'.$suffix.
'" type="hidden" value="'.$alreadyproduced.
'">';
1622 print
'<td>'.$tmpproduct->getNomUrl(1);
1623 print
'<br><span class="opacitymedium small">'.$tmpproduct->label.
'</span>';
1626 print
'<td class="right">'.$line->qty.
'</td>';
1629 print
'<td class="right">'.measuringUnitString($line->fk_unit,
'',
'', 1).
'</td>';
1632 if ($permissiontoupdatecost) {
1634 $manufacturingcost = 0;
1635 $manufacturingcostsrc =
'';
1637 $manufacturingcost = $bomcostupdated;
1638 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1639 if (empty($manufacturingcost)) {
1640 $manufacturingcost = $bomcost;
1641 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1643 if (empty($manufacturingcost)) {
1644 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1645 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1647 if (empty($manufacturingcost)) {
1648 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1649 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1653 print
'<td class="right nowraponall" title="'.dol_escape_htmltag($manufacturingcostsrc).
'">';
1654 if ($manufacturingcost) {
1655 print
price($manufacturingcost);
1660 print
'<td class="right nowraponall">';
1661 if ($alreadyproduced) {
1663 print
'jQuery(document).ready(function() {
1664 jQuery("#expandtoproduce'.$line->id.
'").click(function() {
1665 console.log("Expand mrp_production line '.$line->id.
'");
1666 jQuery(".expanddetailtoproduce'.$line->id.
'").toggle();';
1667 if ($nblinetoproduce == $nblinetoproducecursor) {
1668 print
'if (jQuery("#tablelinestoproduce").hasClass("nobottom")) { jQuery("#tablelinestoproduce").removeClass("nobottom"); } else { jQuery("#tablelinestoproduce").addClass("nobottom"); }';
1674 if (empty(
$conf->use_javascript_ajax)) {
1675 print
'<a href="'.$_SERVER[
"PHP_SELF"].
'?collapse='.$collapse.
','.$line->id.
'">';
1677 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce'.$line->id.
'"');
1678 if (empty(
$conf->use_javascript_ajax)) {
1682 print
' '.$alreadyproduced;
1688 if (isModEnabled(
'productbatch')) {
1698 if ($permissiontodelete) {
1699 if ($line->origin_type ==
'free') {
1700 $href = $_SERVER[
"PHP_SELF"];
1701 $href .=
'?id='.$object->id;
1702 $href .=
'&action=deleteline';
1703 $href .=
'&lineid='.$line->id;
1704 print
'<td class="center">';
1705 print
'<a class="reposition" href="'.$href.
'">';
1706 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
"delete");
1716 foreach ($arrayoflines as $line2) {
1717 print
'<tr class="expanddetailtoproduce'.$line->id.
' hideobject opacitylow">';
1720 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1721 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1731 if ($permissiontoupdatecost) {
1735 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1737 print
'<td class="tdoverflowmax150">';
1738 if ($line2[
'fk_warehouse'] > 0) {
1739 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1741 print $tmpwarehouse->getNomUrl(1);
1746 if (isModEnabled(
'productbatch')) {
1748 if ($line2[
'batch'] !=
'') {
1749 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1750 print $tmpbatch->getNomUrl(1);
1761 if ($permissiontodelete) {
1767 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1768 print
'<!-- Enter line to produce -->'.
"\n";
1770 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1772 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToProduce").
'</span></td>';
1773 $preselected = (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyproduced));
1774 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
1778 print
'<td class="right"><input type="text" class="width50 right" id="qtytoproduce-'.$line->id.
'-'.$i.
'" name="qtytoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1781 print
'<td class="right"></td>';
1784 if ($permissiontoupdatecost) {
1786 $manufacturingcost = 0;
1787 $manufacturingcostsrc =
'';
1789 $manufacturingcost = $bomcostupdated;
1790 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1791 if (empty($manufacturingcost)) {
1792 $manufacturingcost = $bomcost;
1793 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1795 if (empty($manufacturingcost)) {
1796 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1797 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1799 if (empty($manufacturingcost)) {
1800 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1801 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1806 $preselected = (GETPOSTISSET(
'pricetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) : ($manufacturingcost ?
price($manufacturingcost) :
''));
1807 print
'<td class="right"><input type="text" class="width75 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1809 print
'<td><input type="hidden" class="width50 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.($manufacturingcost ? $manufacturingcost :
'').
'"></td>';
1817 $preselected = (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) : (
$object->fk_warehouse > 0 ?
$object->fk_warehouse :
'ifone'));
1818 print $formproduct->selectWarehouses($preselected,
'idwarehousetoproduce-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0, array(),
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1820 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1824 if (isModEnabled(
'productbatch')) {
1826 if ($tmpproduct->status_batch) {
1827 $preselected = (GETPOSTISSET(
'batchtoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i) :
'');
1828 print
'<input type="text" class="width75" name="batchtoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'">';
1832 if ($tmpproduct->status_batch) {
1834 print
'<td align="right" class="split">';
1835 print
img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.$line->id.
', \''.$type.
'\', \
'qtymissing\')"');
1838 print
'<td align="right" class="splitall">';
1839 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1840 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" onClick="addDispatchLine('.$line->id.
', \'batch\', \'alltoproduce\')"');
1866 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline'))) {
1870 <script
type=
"text/javascript" language=
"javascript">
1872 $(document).ready(
function() {
1874 updateselectbatchbywarehouse();
1876 updateselectwarehousebybatch();
1879 function updateselectbatchbywarehouse() {
1880 $(document).on(
'change',
"select[name*='idwarehouse']",
function () {
1881 console.log(
"We change warehouse so we update the list of possible batch number");
1883 var selectwarehouse = $(
this);
1885 var selectbatch_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'batch');
1886 var selectbatch = $(
"datalist[id*='" + selectbatch_name +
"']");
1887 var selectedbatch = selectbatch.val();
1889 var product_element_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'product');
1893 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1895 action:
"updateselectbatchbywarehouse",
1896 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1897 warehouse_id: $(
this).val(),
1898 token:
'<?php echo currentToken(); ?>',
1899 product_id: $(
"input[name='" + product_element_name +
"']").val()
1901 }).done(
function (data) {
1903 selectbatch.empty();
1905 if (typeof data ==
"object") {
1906 console.log(
"data is already type object, no need to parse it");
1908 console.log(
"data is type "+(typeof data));
1909 data = JSON.parse(data);
1912 selectbatch.append($(
'<option>', {
1916 $.each(data,
function (key, value) {
1918 if(selectwarehouse.val() == -1) {
1919 var label = key +
" (<?php echo $langs->trans('Stock total') ?> : " + value +
")";
1921 var label = key +
" (<?php echo $langs->trans('Stock') ?> : " + value +
")";
1924 if(key === selectedbatch) {
1925 var option =
'<option value="'+key+
'" selected>'+ label +
'</option>';
1927 var option =
'<option value="'+key+
'">'+ label +
'</option>';
1930 selectbatch.append(option);
1936 function updateselectwarehousebybatch() {
1937 $(document).on(
'change',
'input[name*=batch]',
function(){
1938 console.log(
"We change batch so we update the list of possible warehouses");
1940 var selectbatch = $(
this);
1942 var selectwarehouse_name = selectbatch.attr(
'name').replace(
'batch',
'idwarehouse');
1943 var selectwarehouse = $(
"select[name*='" + selectwarehouse_name +
"']");
1944 var selectedwarehouse = selectwarehouse.val();
1946 if(selectedwarehouse != -1){
1950 var product_element_name = selectbatch.attr(
'name').replace(
'batch',
'product');
1954 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1956 action:
"updateselectwarehousebybatch",
1957 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1958 batch: $(
this).val(),
1959 token:
'<?php echo currentToken(); ?>',
1960 product_id: $(
"input[name='" + product_element_name +
"']").val()
1962 }).done(
function (data) {
1964 if (typeof data ==
"object") {
1965 console.log(
"data is already type object, no need to parse it");
1967 console.log(
"data is type "+(typeof data));
1968 data = JSON.parse(data);
1972 selectwarehouse.val(data).change();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Class to manage warehouses.
Class to manage stock movements.
Class to manage predefined suppliers products.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class with list of lots and properties.
Class to manage projects.
Class to manage translations.
convertDurationtoHour($duration_value, $duration_unit)
Convert duration to hour.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
newToken()
Return the value of token currently saved into session with name 'newtoken'.
yn($yesno, $format=1, $color=0)
Return yes or no in current language.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='')
Return the value of a $_GET or $_POST supervariable, converted into float.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
moPrepareHead($object)
Prepare array of tabs for Mo.
measuringUnitString($unitid, $measuring_style='', $unitscale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.