29require
'../main.inc.php';
30require_once DOL_DOCUMENT_ROOT.
'/bom/class/bom.class.php';
31require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formcompany.class.php';
32require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formfile.class.php';
33require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formprojet.class.php';
34require_once DOL_DOCUMENT_ROOT.
'/mrp/class/mo.class.php';
35require_once DOL_DOCUMENT_ROOT.
'/mrp/lib/mrp_mo.lib.php';
36require_once DOL_DOCUMENT_ROOT.
'/projet/class/project.class.php';
37require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
38require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
39require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
40require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/productlot.class.php';
41require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
42require_once DOL_DOCUMENT_ROOT.
'/workstation/class/workstation.class.php';
46$langs->loadLangs(array(
"mrp",
"stocks",
"other",
"product",
"productbatch"));
51$action =
GETPOST(
'action',
'aZ09');
52$confirm =
GETPOST(
'confirm',
'alpha');
53$cancel =
GETPOST(
'cancel',
'aZ09');
54$contextpage =
GETPOST(
'contextpage',
'aZ') ?
GETPOST(
'contextpage',
'aZ') :
'mocard';
55$backtopage =
GETPOST(
'backtopage',
'alpha');
58$fk_default_warehouse =
GETPOSTINT(
'fk_default_warehouse');
60$collapse =
GETPOST(
'collapse',
'aZ09comma');
65$diroutputmassaction = $conf->mrp->dir_output.
'/temp/massgeneration/'.$user->id;
66$objectline =
new MoLine($db);
68$hookmanager->initHooks(array(
'moproduction',
'globalcard'));
71$extrafields->fetch_name_optionals_label(
$object->table_element);
73$search_array_options = $extrafields->getOptionalsFromPost(
$object->table_element,
'',
'search_');
76$search_all =
GETPOST(
"search_all",
'alpha');
78foreach (
$object->fields as $key => $val) {
79 if (
GETPOST(
'search_'.$key,
'alpha')) {
80 $search[$key] =
GETPOST(
'search_'.$key,
'alpha');
84if (empty($action) && empty($id) && empty($ref)) {
89include DOL_DOCUMENT_ROOT.
'/core/actions_fetchobject.inc.php';
94$isdraft = ((
$object->status == $object::STATUS_DRAFT) ? 1 : 0);
98$permissionnote = $user->hasRight(
'mrp',
'write');
99$permissiondellink = $user->hasRight(
'mrp',
'write');
100$permissiontoadd = $user->hasRight(
'mrp',
'write');
101$permissiontodelete = $user->hasRight(
'mrp',
'delete') || ($permissiontoadd && isset(
$object->status) &&
$object->status == $object::STATUS_DRAFT);
103$permissiontoproduce = $permissiontoadd;
104$permissiontoupdatecost = $user->hasRight(
'bom',
'read');
106$upload_dir = $conf->mrp->multidir_output[isset(
$object->entity) ?
$object->entity : 1];
113$parameters = array();
114$reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
119if (empty($reshook)) {
122 $backurlforlist = DOL_URL_ROOT.
'/mrp/mo_list.php';
124 if (empty($backtopage) || ($cancel && empty($id))) {
126 if (empty($id) && (($action !=
'add' && $action !=
'create') || $cancel)) {
127 $backtopage = $backurlforlist;
129 $backtopage = DOL_URL_ROOT.
'/mrp/mo_production.php?id='.($id > 0 ? $id :
'__ID__');
132 $triggermodname =
'MO_MODIFY';
134 if ($action ==
'confirm_cancel' && $confirm ==
'yes' && !empty($permissiontoadd)) {
135 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
136 $result =
$object->cancel($user, 0, $also_cancel_consumed_and_produced_lines);
138 header(
"Location: " . DOL_URL_ROOT.
'/mrp/mo_card.php?id=' .
$object->id);
144 } elseif ($action ==
'confirm_delete' && $confirm ==
'yes' && !empty($permissiontodelete)) {
145 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
146 $result =
$object->delete($user, 0, $also_cancel_consumed_and_produced_lines);
148 header(
"Location: " . $backurlforlist);
157 include DOL_DOCUMENT_ROOT.
'/core/actions_addupdatedelete.inc.php';
160 include DOL_DOCUMENT_ROOT.
'/core/actions_dellink.inc.php';
163 include DOL_DOCUMENT_ROOT.
'/core/actions_printing.inc.php';
166 $triggersendname =
'MO_SENTBYMAIL';
167 $autocopy =
'MAIN_MAIL_AUTOCOPY_MO_TO';
168 $trackid =
'mo'.$object->id;
169 include DOL_DOCUMENT_ROOT.
'/core/actions_sendmails.inc.php';
174 if ($action ==
'set_thirdparty' && $permissiontoadd) {
175 $object->setValueFrom(
'fk_soc',
GETPOSTINT(
'fk_soc'),
'',
'',
'date',
'', $user, $triggermodname);
177 if ($action ==
'classin' && $permissiontoadd) {
181 if ($action ==
'confirm_reopen' && $permissiontoadd) {
182 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_REOPEN');
185 if (($action ==
'confirm_addconsumeline' &&
GETPOST(
'addconsumelinebutton') && $permissiontoadd)
186 || ($action ==
'confirm_addproduceline' &&
GETPOST(
'addproducelinebutton') && $permissiontoadd)) {
187 $moline =
new MoLine($db);
192 $moline->fk_product =
GETPOSTINT(
'productidtoadd');
193 if (
GETPOST(
'addconsumelinebutton')) {
194 $moline->role =
'toconsume';
196 $moline->role =
'toproduce';
198 $moline->origin_type =
'free';
199 $moline->position = 0;
202 if (!empty($moline->fk_product)) {
203 $tmpproduct =
new Product($db);
204 $tmpproduct->fetch($moline->fk_product);
206 $moline->fk_default_workstation = $tmpproduct->fk_default_workstation;
210 $moline->fk_unit = $tmpproduct->fk_unit;
214 $extralabelsline = $extrafields->fetch_name_optionals_label(
$object->table_element_line);
215 $array_options = $extrafields->getOptionalsFromPost(
$object->table_element_line);
217 if (is_array($extralabelsline)) {
219 foreach ($extralabelsline as $key => $value) {
220 unset($_POST[
"options_".$key]);
223 if (is_array($array_options) && count($array_options) > 0) {
224 $moline->array_options = $array_options;
227 $resultline = $moline->create($user,
false);
228 if ($resultline <= 0) {
235 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
239 if (in_array($action, array(
'confirm_consumeorproduce',
'confirm_consumeandproduceall')) && $permissiontoproduce) {
242 $labelmovement =
GETPOST(
'inventorylabel',
'alphanohtml');
243 $codemovement =
GETPOST(
'inventorycode',
'alphanohtml');
248 foreach (
$object->lines as $line) {
249 if ($line->role ==
'toconsume') {
250 $tmpproduct =
new Product($db);
251 $tmpproduct->fetch($line->fk_product);
254 while (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
257 if ($qtytoprocess != 0) {
259 if (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i)) {
260 if (!(
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0)) {
261 $langs->load(
"errors");
262 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
265 if ($tmpproduct->status_batch && (!
GETPOST(
'batch-'.$line->id.
'-'.$i))) {
266 $langs->load(
"errors");
267 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
273 if (!$error &&
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0) {
275 $id_product_batch = 0;
277 $stockmove->context[
'mrp_role'] =
'toconsume';
279 if ($qtytoprocess >= 0) {
280 $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);
282 $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);
284 if ($idstockmove < 0) {
292 $moline =
new MoLine($db);
294 $moline->position = $pos;
295 $moline->fk_product = $line->fk_product;
296 $moline->fk_warehouse =
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i);
297 $moline->qty = $qtytoprocess;
298 $moline->batch =
GETPOST(
'batch-'.$line->id.
'-'.$i);
299 $moline->role =
'consumed';
300 $moline->fk_mrp_production = $line->id;
301 $moline->fk_stock_movement = $idstockmove == 0 ? null : $idstockmove;
302 $moline->fk_user_creat = $user->id;
304 $resultmoline = $moline->create($user);
305 if ($resultmoline <= 0) {
322 foreach (
$object->lines as $line) {
323 if ($line->role ==
'toproduce') {
324 $tmpproduct =
new Product($db);
325 $tmpproduct->fetch($line->fk_product);
328 while (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
329 $qtytoprocess = (float)
price2num(
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i));
330 $pricetoprocess =
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) ?
price2num(
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i)) : 0;
332 if ($qtytoprocess != 0) {
334 if (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i)) {
335 if (!(
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0)) {
336 $langs->load(
"errors");
337 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
340 if (isModEnabled(
'productbatch') && $tmpproduct->status_batch && (!
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i))) {
341 $langs->load(
"errors");
342 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
348 if (!$error &&
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0) {
350 $id_product_batch = 0;
351 $stockmove->origin_type =
$object->element;
352 $stockmove->origin_id =
$object->id;
353 $stockmove->context[
'mrp_role'] =
'toproduce';
355 $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);
356 if ($idstockmove < 0) {
364 $moline =
new MoLine($db);
366 $moline->position = $pos;
367 $moline->fk_product = $line->fk_product;
368 $moline->fk_warehouse =
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i);
369 $moline->qty = $qtytoprocess;
370 $moline->batch =
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i);
371 $moline->role =
'produced';
372 $moline->fk_mrp_production = $line->id;
373 $moline->fk_stock_movement = $idstockmove;
374 $moline->fk_user_creat = $user->id;
376 $resultmoline = $moline->create($user);
377 if ($resultmoline <= 0) {
392 $consumptioncomplete =
true;
393 $productioncomplete =
true;
396 foreach (
$object->lines as $line) {
397 if ($line->role ==
'toconsume') {
398 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
399 $alreadyconsumed = 0;
400 foreach ($arrayoflines as $line2) {
401 $alreadyconsumed += $line2[
'qty'];
404 if ($alreadyconsumed < $line->qty) {
405 $consumptioncomplete =
false;
408 if ($line->role ==
'toproduce') {
409 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
410 $alreadyproduced = 0;
411 foreach ($arrayoflines as $line2) {
412 $alreadyproduced += $line2[
'qty'];
415 if ($alreadyproduced < $line->qty) {
416 $productioncomplete =
false;
421 $consumptioncomplete =
false;
422 $productioncomplete =
false;
426 dol_syslog(
"consumptioncomplete = ".json_encode($consumptioncomplete).
" productioncomplete = ".json_encode($productioncomplete));
427 if ($consumptioncomplete && $productioncomplete) {
428 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
430 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_MO_PRODUCED');
439 $action = str_replace(
'confirm_',
'', $action);
445 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
451 if ($action ==
'confirm_produced' && $confirm ==
'yes' && $permissiontoadd) {
452 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
456 $outputlangs = $langs;
459 $newlang =
GETPOST(
'lang_id',
'aZ09');
462 $newlang =
$object->thirdparty->default_lang;
464 if (!empty($newlang)) {
466 $outputlangs->setDefaultLang($newlang);
471 $object->generateDocument($model, $outputlangs, 0, 0, 0);
478 if ($action ==
'confirm_editline' && $permissiontoadd) {
479 $moline =
new MoLine($db);
482 $extrafields->fetch_name_optionals_label($moline->element);
483 foreach ($extrafields->attributes[$moline->table_element][
'label'] as $key => $label) {
484 $value =
GETPOST(
'options_'.$key,
'alphanohtml');
485 $moline->array_options[
"options_".$key] = $value;
488 $res = $moline->update($user);
491 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
494 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
506$form =
new Form($db);
513$help_url =
'EN:Module_Manufacturing_Orders|FR:Module_Ordres_de_Fabrication|DE:Modul_Fertigungsauftrag';
514$morejs = array(
'/mrp/js/lib_dispatch.js.php');
515llxHeader(
'', $langs->trans(
'Mo'), $help_url,
'', 0, 0, $morejs);
520if (
$object->id > 0 && (empty($action) || ($action !=
'edit' && $action !=
'create'))) {
521 $res =
$object->fetch_thirdparty();
522 $res =
$object->fetch_optionals();
525 $tmpwarehouse->fetch(
$object->fk_warehouse);
526 $fk_default_warehouse =
$object->fk_warehouse;
536 if ($action ==
'delete') {
537 $formquestion = array(
539 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
540 'name' =>
'alsoCancelConsumedAndProducedLines',
541 'type' =>
'checkbox',
545 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'DeleteMo'), $langs->trans(
'ConfirmDeleteMo'),
'confirm_delete', $formquestion, 0, 1);
548 if ($action ==
'deleteline') {
549 $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);
552 if ($action ==
'clone') {
554 $formquestion = array();
555 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'ToClone'), $langs->trans(
'ConfirmCloneMo',
$object->ref),
'confirm_clone', $formquestion,
'yes', 1);
559 if ($action ==
'validate') {
561 $ref = substr(
$object->ref, 1, 4);
562 if ($ref ==
'PROV') {
569 $text = $langs->trans(
'ConfirmValidateMo', $numref);
578 $formquestion = array();
579 if (isModEnabled(
'mrp')) {
581 require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
584 if ($conf->browser->name ==
'ie') {
587 $formquestion = array(
594 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'Validate'), $text,
'confirm_validate', $formquestion, 0, 1, 220);
598 if ($action ==
'cancel') {
599 $formquestion = array(
601 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
602 'name' =>
'alsoCancelConsumedAndProducedLines',
603 'type' =>
'checkbox',
604 'value' => !
getDolGlobalString(
'MO_ALSO_CANCEL_CONSUMED_AND_PRODUCED_LINES_BY_DEFAULT') ? 0 : 1
607 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"] .
'?id=' .
$object->id, $langs->trans(
'CancelMo'), $langs->trans(
'ConfirmCancelMo'),
'confirm_cancel', $formquestion, 0, 1);
611 $parameters = array(
'formConfirm' => $formconfirm,
'lineid' => $lineid);
612 $reshook = $hookmanager->executeHooks(
'formConfirm', $parameters, $object, $action);
613 if (empty($reshook)) {
614 $formconfirm .= $hookmanager->resPrint;
615 } elseif ($reshook > 0) {
616 $formconfirm = $hookmanager->resPrint;
625 $linkback =
'<a href="'.DOL_URL_ROOT.
'/mrp/mo_list.php?restore_lastsearch_values=1'.(!empty($socid) ?
'&socid='.$socid :
'').
'">'.$langs->trans(
"BackToList").
'</a>';
627 $morehtmlref =
'<div class="refidno">';
636 if (is_object(
$object->thirdparty)) {
637 $morehtmlref .=
$object->thirdparty->getNomUrl(1,
'customer');
639 $morehtmlref .=
' (<a href="'.DOL_URL_ROOT.
'/commande/list.php?socid='.
$object->thirdparty->id.
'&search_societe='.urlencode(
$object->thirdparty->name).
'">'.$langs->trans(
"OtherOrders").
'</a>)';
644 if (isModEnabled(
'project')) {
645 $langs->load(
"projects");
646 if (is_object(
$object->thirdparty)) {
647 $morehtmlref .=
'<br>';
649 if ($permissiontoadd) {
650 $morehtmlref .=
img_picto($langs->trans(
"Project"),
'project',
'class="pictofixedwidth"');
651 if ($action !=
'classify') {
652 $morehtmlref .=
'<a class="editfielda" href="'.$_SERVER[
'PHP_SELF'].
'?action=classify&token='.
newToken().
'&id='.
$object->id.
'">'.
img_edit($langs->transnoentitiesnoconv(
'SetProject')).
'</a> ';
654 $morehtmlref .= $form->form_project($_SERVER[
'PHP_SELF'].
'?id='.
$object->id,
$object->socid,
$object->fk_project, ($action ==
'classify' ?
'projectid' :
'none'), 0, 0, 0, 1,
'',
'maxwidth300');
656 if (!empty(
$object->fk_project)) {
658 $proj->fetch(
$object->fk_project);
659 $morehtmlref .= $proj->getNomUrl(1);
661 $morehtmlref .=
'<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).
'</span>';
666 $morehtmlref .=
'</div>';
669 dol_banner_tab($object,
'ref', $linkback, 1,
'ref',
'ref', $morehtmlref);
672 print
'<div class="fichecenter">';
673 print
'<div class="fichehalfleft">';
674 print
'<div class="underbanner clearboth"></div>';
675 print
'<table class="border centpercent tableforfield">'.
"\n";
678 $keyforbreak =
'fk_warehouse';
679 unset(
$object->fields[
'fk_project']);
680 unset(
$object->fields[
'fk_soc']);
681 include DOL_DOCUMENT_ROOT.
'/core/tpl/commonfields_view.tpl.php';
684 include DOL_DOCUMENT_ROOT.
'/core/tpl/extrafields_view.tpl.php';
690 print
'<div class="clearboth"></div>';
695 if (!in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
696 print
'<div class="tabsAction">';
698 $parameters = array();
700 $reshook = $hookmanager->executeHooks(
'addMoreActionsButtons', $parameters, $object, $action);
701 if (empty($reshook)) {
703 if (
$object->status == $object::STATUS_DRAFT) {
704 if ($permissiontoadd) {
706 print
'<a class="butAction" href="'.$_SERVER[
'PHP_SELF'].
'?id='.
$object->id.
'&action=validate&token='.$newToken.
'">'.$langs->trans(
"Validate").
'</a>';
708 $langs->load(
"errors");
709 print
'<a class="butActionRefused" href="" title="'.$langs->trans(
"ErrorAddAtLeastOneLineFirst").
'">'.$langs->trans(
"Validate").
'</a>';
715 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
716 if ($permissiontoproduce) {
717 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeorproduce&token='.$newToken.
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
719 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
721 } elseif (
$object->status == Mo::STATUS_DRAFT) {
722 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
726 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
727 if ($permissiontoproduce) {
728 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeandproduceall&token='.$newToken.
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
730 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
732 } elseif (
$object->status == Mo::STATUS_DRAFT) {
733 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
737 if ($permissiontoadd) {
738 if (
$object->status == $object::STATUS_VALIDATED ||
$object->status == $object::STATUS_INPROGRESS) {
739 $arrayproduced =
$object->fetchLinesLinked(
'produced', 0);
741 foreach ($arrayproduced as $lineproduced) {
742 $nbProduced += $lineproduced[
'qty'];
744 if ($nbProduced > 0) {
745 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_produced&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
747 print
'<a class="butActionRefused" href="#" title="'.$langs->trans(
"GoOnTabProductionToProduceFirst", $langs->transnoentitiesnoconv(
"Production")).
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
750 print
'<a class="butActionDelete" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=cancel&token='.$newToken.
'">'.$langs->trans(
"Cancel").
'</a>'.
"\n";
753 if (
$object->status == $object::STATUS_CANCELED) {
754 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"ReOpen").
'</a>'.
"\n";
757 if (
$object->status == $object::STATUS_PRODUCED) {
758 if ($permissiontoproduce) {
759 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&token='.$newToken.
'">'.$langs->trans(
'ReOpen').
'</a>';
761 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ReOpen').
'</a>';
770 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline',
'addproduceline',
'editline'))) {
771 print
'<form method="POST" action="'.$_SERVER[
"PHP_SELF"].
'">';
772 print
'<input type="hidden" name="token" value="'.newToken().
'">';
773 print
'<input type="hidden" name="action" value="confirm_'.$action.
'">';
774 print
'<input type="hidden" name="backtopage" value="'.$backtopage.
'">';
775 print
'<input type="hidden" name="id" value="'.$id.
'">';
778 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
779 $defaultstockmovementlabel =
GETPOST(
'inventorylabel',
'alphanohtml') ?
GETPOST(
'inventorylabel',
'alphanohtml') : $langs->trans(
"ProductionForRef",
$object->
ref);
782 print
'<div class="center'.(in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) ?
' formconsumeproduce' :
'').
'">';
783 print
'<div class="opacitymedium hideonsmartphone paddingbottom">'.$langs->trans(
"ConfirmProductionDesc", $langs->transnoentitiesnoconv(
"Confirm")).
'<br></div>';
784 print
'<span class="fieldrequired">'.$langs->trans(
"InventoryCode").
':</span> <input type="text" class="minwidth150 maxwidth200" name="inventorycode" value="'.$defaultstockmovementcode.
'"> ';
785 print
'<span class="clearbothonsmartphone"></span>';
786 print $langs->trans(
"MovementLabel").
': <input type="text" class="minwidth300" name="inventorylabel" value="'.$defaultstockmovementlabel.
'"><br><br>';
787 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>';
788 print
'<input type="submit" class="button" value="'.$langs->trans(
"Confirm").
'" name="confirm">';
790 print
'<input class="button button-cancel" type="submit" value="'.$langs->trans(
"Cancel").
'" name="cancel">';
804 if (!empty(
$object->table_element_line)) {
811 $res = $bom->fetch(
$object->fk_bom);
813 $bom->calculateCosts();
814 $bomcost = $bom->unit_cost;
820 print
'<div class="fichecenter">';
821 print
'<div class="fichehalfleft">';
822 print
'<div class="clearboth"></div>';
824 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addconsumeline&token='.
newToken();
825 $permissiontoaddaconsumeline =
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED;
826 $parameters = array(
'morecss' =>
'reposition');
829 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
830 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewConsumeLines'),
'',
'fa fa-plus-circle size15x', $url,
'', $permissiontoaddaconsumeline, $parameters);
833 print
load_fiche_titre($langs->trans(
'Consumption'), $newcardbutton,
'', 0,
'',
'',
'');
835 print
'<div class="div-table-responsive-no-min">';
836 print
'<table class="noborder noshadow centpercent nobottom">';
838 print
'<tr class="liste_titre">';
840 print
'<td>'.$langs->trans(
"Product").
'</td>';
842 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
847 print
'<td class="right">'.$langs->trans(
"UnitCost").
'</td>';
850 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyConsumedShort"), $langs->trans(
"QtyAlreadyConsumed")).
'</td>';
853 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
854 print $langs->trans(
"Warehouse");
855 if (isModEnabled(
'workstation')) {
856 print
' '.$langs->trans(
"or").
' '.$langs->trans(
"Workstation");
859 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
860 $listwarehouses = $tmpwarehouse->list_array(1);
861 if (count($listwarehouses) > 1) {
862 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, $langs->trans(
"ForceTo"), 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
863 } elseif (count($listwarehouses) == 1) {
864 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
870 if (isModEnabled(
'stock')) {
872 print
'<td align="right">';
873 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
874 print $langs->trans(
"Stock");
879 if (isModEnabled(
'productbatch')) {
881 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
882 print $langs->trans(
"Batch");
887 if ($permissiontodelete) {
898 if (
$object->status == Mo::STATUS_DRAFT) {
904 if ($action ==
'addconsumeline') {
905 print
'<!-- Add line to consume -->'.
"\n";
906 print
'<tr class="liste_titre">';
909 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
912 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
920 print
'<td colspan="2">';
921 print
'<input type="submit" class="button buttongen button-add" name="addconsumelinebutton" value="'.$langs->trans(
"Add").
'">';
922 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdconsumelinebutton" value="'.$langs->trans(
"Cancel").
'">';
924 if (isModEnabled(
'stock')) {
928 if (isModEnabled(
'productbatch')) {
932 if ($permissiontodelete) {
940 if (
$object->status == Mo::STATUS_DRAFT) {
946 if (is_object($objectline)) {
947 $extrafields->fetch_name_optionals_label(
$object->table_element_line);
948 $temps = $objectline->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
949 if (!empty($temps)) {
950 print
'<tr class="liste_titre"><td style="padding-top: 20px" colspan="9" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
962 $nblinetoconsume = 0;
963 foreach (
$object->lines as $line) {
964 if ($line->role ==
'toconsume') {
969 $nblinetoconsumecursor = 0;
970 foreach (
$object->lines as $line) {
971 if ($line->role ==
'toconsume') {
972 $nblinetoconsumecursor++;
974 $tmpproduct =
new Product($db);
975 $tmpproduct->fetch($line->fk_product);
976 $linecost =
price2num($tmpproduct->pmp,
'MT');
980 $costprice =
price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp);
981 if (empty($costprice)) {
982 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
984 if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) {
985 $costprice = $productFournisseur->fourn_unitprice;
993 if ($useunit && $line->fk_unit > 0) {
996 if (preg_match(
'/^(\d+)([a-z]+)$/', $tmpproduct->duration, $reg)) {
1000 if ($line->fk_unit) {
1005 if ($qtyhourservice && $qtyhourforline) {
1006 $linecost =
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MT');
1007 $bomcostupdated +=
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MU');
1010 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1014 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1018 $bomcostupdated =
price2num($bomcostupdated,
'MU');
1019 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1020 $alreadyconsumed = 0;
1021 foreach ($arrayoflines as $line2) {
1022 $alreadyconsumed += $line2[
'qty'];
1025 if ($action ==
'editline' && $lineid == $line->id) {
1026 $linecost =
price2num($tmpproduct->pmp,
'MT');
1028 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1029 $alreadyconsumed = 0;
1030 if (is_array($arrayoflines) && !empty($arrayoflines)) {
1031 foreach ($arrayoflines as $line2) {
1032 $alreadyconsumed += $line2[
'qty'];
1035 $suffix =
'_' . $line->id;
1036 print
'<!-- Line to dispatch ' . $suffix .
' (line edited) -->' .
"\n";
1038 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1040 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1042 print
'<input name="lineid" type="hidden" value="' . $line->id .
'">';
1045 print
'<td>' . $tmpproduct->getNomUrl(1);
1046 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</span>';
1050 print
'<td class="right nowraponall">';
1051 print
'<input class="width40 right" name="qty_lineProduce" value="'. $line->qty.
'">';
1055 print
'<td class="right nowraponall">';
1063 print
'<td class="right">';
1064 print
' ' .
price2num($alreadyconsumed,
'MS');
1072 print
'<td class="nowraponall right">';
1073 if ($tmpproduct->isStockManaged()) {
1074 if ($tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1075 print
img_warning($langs->trans(
'StockTooLow')).
' ';
1077 print
'<span class="left">'. $tmpproduct->stock_reel .
' </span>';
1088 print
'<td colspan="'.($permissiontodelete ? 4 : 3).
'">';
1089 print
'<input type="submit" class="button buttongen button-add small nominwidth" name="save" value="' . $langs->trans(
"Save") .
'">';
1090 print
'<input type="submit" class="button buttongen button-cancel small nominwidth" name="cancel" value="' . $langs->trans(
"Cancel") .
'">';
1096 if (!empty($extrafields)) {
1097 $line->fetch_optionals();
1098 $temps = $line->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
1099 if (!empty($temps)) {
1100 print
'<td colspan="10"><div style="padding-top: 20px" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
1102 print
'</div></td>';
1106 $suffix =
'_' . $line->id;
1107 print
'<!-- Line to dispatch ' . $suffix .
' -->' .
"\n";
1109 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1110 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1112 print
'<tr data-line-id="' . $line->id .
'">';
1115 print
'<td>' . $tmpproduct->getNomUrl(1);
1116 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</div>';
1120 print
'<td class="right nowraponall">';
1122 if ($line->qty_frozen) {
1123 $help = ($help ?
'<br>' :
'') .
'<strong>' . $langs->trans(
"QuantityFrozen") .
'</strong>: ' .
yn(1) .
' (' . $langs->trans(
"QuantityConsumedInvariable") .
')';
1124 print $form->textwithpicto(
'', $help, -1,
'lock') .
' ';
1126 if ($line->disable_stock_change) {
1127 $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")) .
')';
1128 print $form->textwithpicto(
'', $help, -1,
'help') .
' ';
1134 print
'<td class="right nowraponall">';
1142 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1143 print
'<td class="right nowraponall">';
1144 print
price($linecost);
1149 print
'<td class="right">';
1150 if ($alreadyconsumed) {
1152 print
'jQuery(document).ready(function() {
1153 jQuery("#expandtoproduce' . $line->id .
'").click(function() {
1154 console.log("Expand mrp_production line ' . $line->id .
'");
1155 jQuery(".expanddetail' . $line->id .
'").toggle();';
1156 if ($nblinetoconsume == $nblinetoconsumecursor) {
1157 print
'if (jQuery("#tablelines").hasClass("nobottom")) { jQuery("#tablelines").removeClass("nobottom"); } else { jQuery("#tablelines").addClass("nobottom"); }';
1163 if (empty($conf->use_javascript_ajax)) {
1164 print
'<a href="' . $_SERVER[
"PHP_SELF"] .
'?collapse=' . $collapse .
',' . $line->id .
'">';
1166 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce' . $line->id .
'"');
1167 if (empty($conf->use_javascript_ajax)) {
1171 if ($nblinetoconsume == $nblinetoconsumecursor) {
1172 print
'<script>jQuery("#tablelines").removeClass("nobottom");</script>';
1175 print
' ' .
price2num($alreadyconsumed,
'MS');
1179 if (
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') && $tmpwarehouse->id > 0) {
1180 print
img_picto(
'', $tmpwarehouse->picto) .
" " . $tmpwarehouse->label;
1182 if (isModEnabled(
'workstation') && $line->fk_default_workstation > 0) {
1184 $tmpworkstation->fetch($line->fk_default_workstation);
1185 print $tmpworkstation->getNomUrl(1);
1189 if (isModEnabled(
'stock')) {
1190 print
'<td class="nowraponall right">';
1192 if (!$line->disable_stock_change && $tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1193 print
img_warning($langs->trans(
'StockTooLow')) .
' ';
1195 if (!
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') || empty($tmpwarehouse->id)) {
1196 print
price2num($tmpproduct->stock_reel,
'MS');
1199 $tmpproduct->load_stock();
1200 $wh_stock = $tmpproduct->stock_warehouse[$tmpwarehouse->id];
1201 if (!empty($wh_stock)) {
1211 if (isModEnabled(
'productbatch')) {
1222 if (
$object->status == Mo::STATUS_DRAFT) {
1223 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1224 print
'<td class="center">';
1225 print
'<a class="reposition editfielda" href="' . $href .
'">';
1226 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1232 if ($permissiontodelete) {
1233 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=deleteline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1234 print
'<td class="center">';
1235 print
'<a class="reposition" href="' . $href .
'">';
1236 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1243 if (!empty($extrafields)) {
1244 $line->fetch_optionals();
1245 $temps = $line->showOptionals($extrafields,
'view', array(),
'',
'', 1,
'line');
1246 if (!empty($temps)) {
1247 print
'<td colspan="10"><div id="extrafield_lines_area_'.$line->id.
'" name="extrafield_lines_area_'.$line->id.
'">';
1249 print
'</div></td>';
1254 foreach ($arrayoflines as $line2) {
1255 print
'<tr class="expanddetail'.$line->id.
' hideobject opacitylow">';
1259 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1260 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1268 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1271 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1276 print
'<td class="tdoverflowmax150">';
1277 if ($line2[
'fk_warehouse'] > 0) {
1278 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1280 print $tmpwarehouse->getNomUrl(1);
1286 if (isModEnabled(
'stock')) {
1291 if (isModEnabled(
'productbatch')) {
1293 if ($line2[
'batch'] !=
'') {
1294 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1295 print $tmpbatch->getNomUrl(1);
1307 if (
$object->status == Mo::STATUS_DRAFT) {
1308 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line2[
'rowid']);
1309 print
'<td class="center">';
1310 print
'<a class="reposition" href="' . $href .
'">';
1311 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1317 if ($permissiontodelete) {
1318 $href = $_SERVER[
"PHP_SELF"].
'?id='.((int)
$object->id).
'&action=deleteline&token='.
newToken().
'&lineid='.((int) $line2[
'rowid']).
'&fk_movement='.((int) $line2[
'fk_stock_movement']);
1319 print
'<td class="center">';
1320 print
'<a class="reposition" href="'.$href.
'">';
1321 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1329 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1331 print
'<!-- Enter line to consume -->'.
"\n";
1333 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1335 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToConsume").
'</span></td>';
1336 $preselected = (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i) ?
GETPOST(
'qty-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyconsumed));
1337 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
1342 if (
getDolGlobalString(
'MRP_NEVER_CONSUME_MORE_THAN_EXPECTED') && ($line->qty - $alreadyconsumed) <= 0) {
1343 $disable =
'disabled';
1347 print
'<input type="hidden" name="product-'.$line->id.
'-'.$i.
'" value="'.$line->fk_product.
'">';
1350 print
'<td class="right"><input type="text" class="width50 right" id="qtytoconsume-' . $line->id .
'-' . $i .
'" name="qty-' . $line->id .
'-' . $i .
'" value="' . $preselected .
'" ' . $disable .
'></td>';
1358 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1368 if (empty($line->disable_stock_change)) {
1369 $preselected = (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) : ($tmpproduct->fk_default_warehouse > 0 ? $tmpproduct->fk_default_warehouse :
'ifone'));
1370 print $formproduct->selectWarehouses($preselected,
'idwarehouse-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0,
null,
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1372 print
'<span class="opacitymedium">'.$langs->trans(
"DisableStockChange").
'</span>';
1375 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1380 if (isModEnabled(
'stock')) {
1385 if (isModEnabled(
'productbatch')) {
1386 print
'<td class="nowraponall">';
1387 if ($tmpproduct->status_batch) {
1388 $preselected = (GETPOSTISSET(
'batch-'.$line->id.
'-'.$i) ?
GETPOST(
'batch-'.$line->id.
'-'.$i) :
'');
1389 print
'<input type="text" class="width75" name="batch-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'" list="batch-'.$line->id.
'-'.$i.
'">';
1390 print $formproduct->selectLotDataList(
'batch-'.$line->id.
'-'.$i, 0, $line->fk_product,
'',
'');
1397 print
'<td align="right" class="split">';
1398 print
' '.img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.((int) $line->id).
', \''.
dol_escape_js($type).
'\', \
'qtymissingconsume\')"');
1402 print
'<td align="right" class="splitall">';
1403 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1404 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" data-max-qty="1" onClick="addDispatchLine('.$line->id.
', \'batch\', \'allmissingconsume\')"');
1409 if (
$object->status == Mo::STATUS_DRAFT) {
1414 if ($permissiontodelete) {
1428 print
'<script type="text/javascript">
1429 $(document).ready(function () {
1430 $("select[name=fk_default_warehouse]").change(function() {
1431 var fk_default_warehouse = $("option:selected", this).val();
1432 $("select[name^=idwarehouse-]").val(fk_default_warehouse).change();
1437 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) &&
1439 print
'<script>$(document).ready(function () {
1440 $("#fk_default_warehouse").change();
1448 print
'<div class="fichehalfright">';
1449 print
'<div class="clearboth"></div>';
1451 $nblinetoproduce = 0;
1452 foreach (
$object->lines as $line) {
1453 if ($line->role ==
'toproduce') {
1458 $newcardbutton =
'';
1459 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addproduceline&token='.
newToken();
1460 $permissiontoaddaproductline =
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED;
1461 $parameters = array(
'morecss' =>
'reposition');
1462 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
1463 if ($nblinetoproduce == 0 ||
$object->mrptype == 1) {
1464 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewProduceLines'),
'',
'fa fa-plus-circle size15x', $url,
'', $permissiontoaddaproductline, $parameters);
1468 print
load_fiche_titre($langs->trans(
'Production'), $newcardbutton,
'', 0,
'',
'');
1470 print
'<div class="div-table-responsive-no-min">';
1471 print
'<table id="tablelinestoproduce" class="noborder noshadow nobottom centpercent">';
1473 print
'<tr class="liste_titre">';
1475 print
'<td>'.$langs->trans(
"Product").
'</td>';
1477 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
1480 print
'<td class="right">'.$langs->trans(
"Unit").
'</td>';
1483 if ($permissiontoupdatecost) {
1484 if (empty($bomcostupdated)) {
1485 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"UnitCost"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1487 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"ManufacturingPrice"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1491 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyProducedShort"), $langs->trans(
"QtyAlreadyProduced")).
'</td>';
1494 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1495 print $langs->trans(
"Warehouse");
1500 if (isModEnabled(
'productbatch')) {
1502 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1503 print $langs->trans(
"Batch");
1515 if ($permissiontodelete) {
1521 if ($action ==
'addproduceline') {
1522 print
'<!-- Add line to produce -->'.
"\n";
1523 print
'<tr class="liste_titre">';
1527 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
1530 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
1536 if ($permissiontoupdatecost) {
1540 print
'<td colspan="2">';
1541 print
'<input type="submit" class="button buttongen button-add" name="addproducelinebutton" value="'.$langs->trans(
"Add").
'">';
1542 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdproducelinebutton" value="'.$langs->trans(
"Cancel").
'">';
1545 if (isModEnabled(
'productbatch')) {
1555 if ($permissiontodelete) {
1562 $nblinetoproduce = 0;
1563 foreach (
$object->lines as $line) {
1564 if ($line->role ==
'toproduce') {
1569 $nblinetoproducecursor = 0;
1570 foreach (
$object->lines as $line) {
1571 if ($line->role ==
'toproduce') {
1574 $nblinetoproducecursor++;
1576 $tmpproduct =
new Product($db);
1577 $tmpproduct->fetch($line->fk_product);
1579 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
1580 $alreadyproduced = 0;
1581 foreach ($arrayoflines as $line2) {
1582 $alreadyproduced += $line2[
'qty'];
1585 $suffix =
'_'.$line->id;
1586 print
'<!-- Line to dispatch '.$suffix.
' (toproduce) -->'.
"\n";
1588 print
'<input id="qty_ordered'.$suffix.
'" type="hidden" value="'.$line->qty.
'">';
1589 print
'<input id="qty_dispatched'.$suffix.
'" type="hidden" value="'.$alreadyproduced.
'">';
1593 print
'<td>'.$tmpproduct->getNomUrl(1);
1594 print
'<br><span class="opacitymedium small">'.$tmpproduct->label.
'</span>';
1597 print
'<td class="right">'.$line->qty.
'</td>';
1600 print
'<td class="right">'.measuringUnitString($line->fk_unit,
'',
'', 1).
'</td>';
1603 if ($permissiontoupdatecost) {
1605 $manufacturingcost = 0;
1606 $manufacturingcostsrc =
'';
1608 $manufacturingcost = $bomcostupdated;
1609 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1610 if (empty($manufacturingcost)) {
1611 $manufacturingcost = $bomcost;
1612 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1614 if (empty($manufacturingcost)) {
1615 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1616 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1618 if (empty($manufacturingcost)) {
1619 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1620 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1624 print
'<td class="right nowraponall" title="'.dol_escape_htmltag($manufacturingcostsrc).
'">';
1625 if ($manufacturingcost) {
1626 print
price($manufacturingcost);
1631 print
'<td class="right nowraponall">';
1632 if ($alreadyproduced) {
1634 print
'jQuery(document).ready(function() {
1635 jQuery("#expandtoproduce'.$line->id.
'").click(function() {
1636 console.log("Expand mrp_production line '.$line->id.
'");
1637 jQuery(".expanddetailtoproduce'.$line->id.
'").toggle();';
1638 if ($nblinetoproduce == $nblinetoproducecursor) {
1639 print
'if (jQuery("#tablelinestoproduce").hasClass("nobottom")) { jQuery("#tablelinestoproduce").removeClass("nobottom"); } else { jQuery("#tablelinestoproduce").addClass("nobottom"); }';
1645 if (empty($conf->use_javascript_ajax)) {
1646 print
'<a href="'.$_SERVER[
"PHP_SELF"].
'?collapse='.$collapse.
','.$line->id.
'">';
1648 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce'.$line->id.
'"');
1649 if (empty($conf->use_javascript_ajax)) {
1653 print
' '.$alreadyproduced;
1659 if (isModEnabled(
'productbatch')) {
1669 if ($permissiontodelete) {
1670 if ($line->origin_type ==
'free') {
1671 $href = $_SERVER[
"PHP_SELF"];
1672 $href .=
'?id='.$object->id;
1673 $href .=
'&action=deleteline';
1674 $href .=
'&lineid='.$line->id;
1675 print
'<td class="center">';
1676 print
'<a class="reposition" href="'.$href.
'">';
1677 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
"delete");
1687 foreach ($arrayoflines as $line2) {
1688 print
'<tr class="expanddetailtoproduce'.$line->id.
' hideobject opacitylow">';
1691 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1692 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1702 if ($permissiontoupdatecost) {
1706 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1708 print
'<td class="tdoverflowmax150">';
1709 if ($line2[
'fk_warehouse'] > 0) {
1710 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1712 print $tmpwarehouse->getNomUrl(1);
1717 if (isModEnabled(
'productbatch')) {
1719 if ($line2[
'batch'] !=
'') {
1720 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1721 print $tmpbatch->getNomUrl(1);
1732 if ($permissiontodelete) {
1738 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1739 print
'<!-- Enter line to produce -->'.
"\n";
1741 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1743 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToProduce").
'</span></td>';
1744 $preselected = (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyproduced));
1745 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
1749 print
'<td class="right"><input type="text" class="width50 right" id="qtytoproduce-'.$line->id.
'-'.$i.
'" name="qtytoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1752 print
'<td class="right"></td>';
1755 if ($permissiontoupdatecost) {
1757 $manufacturingcost = 0;
1758 $manufacturingcostsrc =
'';
1760 $manufacturingcost = $bomcostupdated;
1761 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1762 if (empty($manufacturingcost)) {
1763 $manufacturingcost = $bomcost;
1764 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1766 if (empty($manufacturingcost)) {
1767 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1768 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1770 if (empty($manufacturingcost)) {
1771 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1772 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1777 $preselected = (GETPOSTISSET(
'pricetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) : ($manufacturingcost ?
price($manufacturingcost) :
''));
1778 print
'<td class="right"><input type="text" class="width75 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1780 print
'<td><input type="hidden" class="width50 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.($manufacturingcost ? $manufacturingcost :
'').
'"></td>';
1788 $preselected = (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) : (
$object->fk_warehouse > 0 ?
$object->fk_warehouse :
'ifone'));
1789 print $formproduct->selectWarehouses($preselected,
'idwarehousetoproduce-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0,
null,
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1791 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1795 if (isModEnabled(
'productbatch')) {
1797 if ($tmpproduct->status_batch) {
1798 $preselected = (GETPOSTISSET(
'batchtoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i) :
'');
1799 print
'<input type="text" class="width75" name="batchtoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'">';
1803 if ($tmpproduct->status_batch) {
1805 print
'<td align="right" class="split">';
1806 print
img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.$line->id.
', \''.$type.
'\', \
'qtymissing\')"');
1809 print
'<td align="right" class="splitall">';
1810 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1811 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" onClick="addDispatchLine('.$line->id.
', \'batch\', \'alltoproduce\')"');
1837 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline'))) {
1841 <script
type=
"text/javascript" language=
"javascript">
1843 $(document).ready(
function() {
1845 updateselectbatchbywarehouse();
1847 updateselectwarehousebybatch();
1850 function updateselectbatchbywarehouse() {
1851 $(document).on(
'change',
"select[name*='idwarehouse']",
function () {
1852 console.log(
"We change warehouse so we update the list of possible batch number");
1854 var selectwarehouse = $(
this);
1856 var selectbatch_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'batch');
1857 var selectbatch = $(
"datalist[id*='" + selectbatch_name +
"']");
1858 var selectedbatch = selectbatch.val();
1860 var product_element_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'product');
1864 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1866 action:
"updateselectbatchbywarehouse",
1867 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1868 warehouse_id: $(
this).val(),
1869 token:
'<?php echo currentToken(); ?>',
1870 product_id: $(
"input[name='" + product_element_name +
"']").val()
1872 }).done(
function (data) {
1874 selectbatch.empty();
1876 if (typeof data ==
"object") {
1877 console.log(
"data is already type object, no need to parse it");
1879 console.log(
"data is type "+(typeof data));
1880 data = JSON.parse(data);
1883 selectbatch.append($(
'<option>', {
1887 $.each(data,
function (key, value) {
1889 if(selectwarehouse.val() == -1) {
1890 var label =
" (<?php echo $langs->trans('Stock total') ?> : " + value +
")";
1892 var label =
" (<?php echo $langs->trans('Stock') ?> : " + value +
")";
1895 if(key === selectedbatch) {
1896 var option =
'<option value="'+key+
'" selected>'+ label +
'</option>';
1898 var option =
'<option value="'+key+
'">'+ label +
'</option>';
1901 selectbatch.append(option);
1907 function updateselectwarehousebybatch() {
1908 $(document).on(
'change',
'input[name*=batch]',
function(){
1909 console.log(
"We change batch so we update the list of possible warehouses");
1911 var selectbatch = $(
this);
1913 var selectwarehouse_name = selectbatch.attr(
'name').replace(
'batch',
'idwarehouse');
1914 var selectwarehouse = $(
"select[name*='" + selectwarehouse_name +
"']");
1915 var selectedwarehouse = selectwarehouse.val();
1917 if(selectedwarehouse != -1){
1921 var product_element_name = selectbatch.attr(
'name').replace(
'batch',
'product');
1925 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1927 action:
"updateselectwarehousebybatch",
1928 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1929 batch: $(
this).val(),
1930 token:
'<?php echo currentToken(); ?>',
1931 product_id: $(
"input[name='" + product_element_name +
"']").val()
1933 }).done(
function (data) {
1935 if (typeof data ==
"object") {
1936 console.log(
"data is already type object, no need to parse it");
1938 console.log(
"data is type "+(typeof data));
1939 data = JSON.parse(data);
1943 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()
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.
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.
yn($yesno, $case=1, $color=0)
Return yes or no in current language.
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'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
getDolGlobalString($key, $default='')
Return 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...
moPrepareHead($object)
Prepare array of tabs for Mo.
measuringUnitString($unit, $measuring_style='', $scale='', $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.