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';
47$langs->loadLangs(array(
"mrp",
"stocks",
"other",
"product",
"productbatch"));
52$action =
GETPOST(
'action',
'aZ09');
53$confirm =
GETPOST(
'confirm',
'alpha');
54$cancel =
GETPOST(
'cancel',
'aZ09');
55$contextpage =
GETPOST(
'contextpage',
'aZ') ?
GETPOST(
'contextpage',
'aZ') :
'mocard';
56$backtopage =
GETPOST(
'backtopage',
'alpha');
59$fk_default_warehouse =
GETPOSTINT(
'fk_default_warehouse');
61$collapse =
GETPOST(
'collapse',
'aZ09comma');
66$diroutputmassaction = $conf->mrp->dir_output.
'/temp/massgeneration/'.$user->id;
67$objectline =
new MoLine($db);
69$hookmanager->initHooks(array(
'moproduction',
'globalcard'));
72$extrafields->fetch_name_optionals_label(
$object->table_element);
74$search_array_options = $extrafields->getOptionalsFromPost(
$object->table_element,
'',
'search_');
77$search_all =
GETPOST(
"search_all",
'alpha');
79foreach (
$object->fields as $key => $val) {
80 if (
GETPOST(
'search_'.$key,
'alpha')) {
81 $search[$key] =
GETPOST(
'search_'.$key,
'alpha');
85if (empty($action) && empty($id) && empty($ref)) {
90include DOL_DOCUMENT_ROOT.
'/core/actions_fetchobject.inc.php';
95$isdraft = ((
$object->status == $object::STATUS_DRAFT) ? 1 : 0);
99$permissionnote = $user->hasRight(
'mrp',
'write');
100$permissiondellink = $user->hasRight(
'mrp',
'write');
101$permissiontoadd = $user->hasRight(
'mrp',
'write');
102$permissiontodelete = $user->hasRight(
'mrp',
'delete') || ($permissiontoadd && isset(
$object->status) &&
$object->status == $object::STATUS_DRAFT);
104$permissiontoproduce = $permissiontoadd;
105$permissiontoupdatecost = $user->hasRight(
'bom',
'read');
107$upload_dir = $conf->mrp->multidir_output[isset(
$object->entity) ?
$object->entity : 1];
114$parameters = array();
115$reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
120if (empty($reshook)) {
123 $backurlforlist = DOL_URL_ROOT.
'/mrp/mo_list.php';
125 if (empty($backtopage) || ($cancel && empty($id))) {
127 if (empty($id) && (($action !=
'add' && $action !=
'create') || $cancel)) {
128 $backtopage = $backurlforlist;
130 $backtopage = DOL_URL_ROOT.
'/mrp/mo_production.php?id='.(
$id > 0 ?
$id :
'__ID__');
133 $triggermodname =
'MO_MODIFY';
135 if ($action ==
'confirm_cancel' && $confirm ==
'yes' && !empty($permissiontoadd)) {
136 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
137 $result =
$object->cancel($user, 0, $also_cancel_consumed_and_produced_lines);
139 header(
"Location: " . DOL_URL_ROOT.
'/mrp/mo_card.php?id=' .
$object->id);
145 } elseif ($action ==
'confirm_delete' && $confirm ==
'yes' && !empty($permissiontodelete)) {
146 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
147 $result =
$object->delete($user, 0, $also_cancel_consumed_and_produced_lines);
149 header(
"Location: " . $backurlforlist);
158 include DOL_DOCUMENT_ROOT.
'/core/actions_addupdatedelete.inc.php';
161 include DOL_DOCUMENT_ROOT.
'/core/actions_dellink.inc.php';
164 include DOL_DOCUMENT_ROOT.
'/core/actions_printing.inc.php';
167 $triggersendname =
'MO_SENTBYMAIL';
168 $autocopy =
'MAIN_MAIL_AUTOCOPY_MO_TO';
169 $trackid =
'mo'.$object->id;
170 include DOL_DOCUMENT_ROOT.
'/core/actions_sendmails.inc.php';
175 if ($action ==
'set_thirdparty' && $permissiontoadd) {
176 $object->setValueFrom(
'fk_soc',
GETPOSTINT(
'fk_soc'),
'',
null,
'date',
'', $user, $triggermodname);
178 if ($action ==
'classin' && $permissiontoadd) {
182 if ($action ==
'confirm_reopen' && $permissiontoadd) {
183 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_REOPEN');
186 if (($action ==
'confirm_addconsumeline' &&
GETPOST(
'addconsumelinebutton') && $permissiontoadd)
187 || ($action ==
'confirm_addproduceline' &&
GETPOST(
'addproducelinebutton') && $permissiontoadd)) {
188 $moline =
new MoLine($db);
193 $moline->fk_product =
GETPOSTINT(
'productidtoadd');
194 if (
GETPOST(
'addconsumelinebutton')) {
195 $moline->role =
'toconsume';
197 $moline->role =
'toproduce';
199 $moline->origin_type =
'free';
200 $moline->position = 0;
203 if (!empty($moline->fk_product)) {
204 $tmpproduct =
new Product($db);
205 $tmpproduct->fetch($moline->fk_product);
207 $moline->fk_default_workstation = $tmpproduct->fk_default_workstation;
211 $moline->fk_unit = $tmpproduct->fk_unit;
215 $extralabelsline = $extrafields->fetch_name_optionals_label(
$object->table_element_line);
216 $array_options = $extrafields->getOptionalsFromPost(
$object->table_element_line);
218 if (is_array($extralabelsline)) {
220 foreach ($extralabelsline as $key => $value) {
221 unset($_POST[
"options_".$key]);
224 if (is_array($array_options) && count($array_options) > 0) {
225 $moline->array_options = $array_options;
228 $resultline = $moline->create($user,
false);
229 if ($resultline <= 0) {
236 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
240 if (in_array($action, array(
'confirm_consumeorproduce',
'confirm_consumeandproduceall')) && $permissiontoproduce) {
243 $labelmovement =
GETPOST(
'inventorylabel',
'alphanohtml');
244 $codemovement =
GETPOST(
'inventorycode',
'alphanohtml');
249 foreach (
$object->lines as $line) {
250 if ($line->role ==
'toconsume') {
251 $tmpproduct =
new Product($db);
252 $tmpproduct->fetch($line->fk_product);
255 while (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
258 if ($qtytoprocess != 0) {
260 if (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i)) {
261 if (!(
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0)) {
262 $langs->load(
"errors");
263 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
266 if ($tmpproduct->status_batch && (!
GETPOST(
'batch-'.$line->id.
'-'.$i))) {
267 $langs->load(
"errors");
268 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
274 if (!$error &&
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0) {
276 $id_product_batch = 0;
278 $stockmove->context[
'mrp_role'] =
'toconsume';
280 if ($qtytoprocess >= 0) {
281 $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);
283 $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);
285 if ($idstockmove < 0) {
293 $moline =
new MoLine($db);
295 $moline->position = $pos;
296 $moline->fk_product = $line->fk_product;
297 $moline->fk_warehouse =
GETPOSTINT(
'idwarehouse-'.$line->id.
'-'.$i);
298 $moline->qty = $qtytoprocess;
299 $moline->batch =
GETPOST(
'batch-'.$line->id.
'-'.$i);
300 $moline->role =
'consumed';
301 $moline->fk_mrp_production = $line->id;
302 $moline->fk_stock_movement = $idstockmove == 0 ? null : $idstockmove;
303 $moline->fk_user_creat = $user->id;
305 $resultmoline = $moline->create($user);
306 if ($resultmoline <= 0) {
323 foreach (
$object->lines as $line) {
324 if ($line->role ==
'toproduce') {
325 $tmpproduct =
new Product($db);
326 $tmpproduct->fetch($line->fk_product);
329 while (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
330 $qtytoprocess = (float)
price2num(
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i));
331 $pricetoprocess =
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) ?
price2num(
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i)) : 0;
333 if ($qtytoprocess != 0) {
335 if (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i)) {
336 if (!(
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0)) {
337 $langs->load(
"errors");
338 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
341 if (isModEnabled(
'productbatch') && $tmpproduct->status_batch && (!
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i))) {
342 $langs->load(
"errors");
343 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
349 if (!$error &&
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0) {
351 $id_product_batch = 0;
352 $stockmove->origin_type =
$object->element;
353 $stockmove->origin_id =
$object->id;
354 $stockmove->context[
'mrp_role'] =
'toproduce';
356 $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);
357 if ($idstockmove < 0) {
365 $moline =
new MoLine($db);
367 $moline->position = $pos;
368 $moline->fk_product = $line->fk_product;
369 $moline->fk_warehouse =
GETPOSTINT(
'idwarehousetoproduce-'.$line->id.
'-'.$i);
370 $moline->qty = $qtytoprocess;
371 $moline->batch =
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i);
372 $moline->role =
'produced';
373 $moline->fk_mrp_production = $line->id;
374 $moline->fk_stock_movement = $idstockmove;
375 $moline->fk_user_creat = $user->id;
377 $resultmoline = $moline->create($user);
378 if ($resultmoline <= 0) {
393 $consumptioncomplete =
true;
394 $productioncomplete =
true;
397 foreach (
$object->lines as $line) {
398 if ($line->role ==
'toconsume') {
399 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
400 $alreadyconsumed = 0;
401 foreach ($arrayoflines as $line2) {
402 $alreadyconsumed += $line2[
'qty'];
405 if ($alreadyconsumed < $line->qty) {
406 $consumptioncomplete =
false;
409 if ($line->role ==
'toproduce') {
410 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
411 $alreadyproduced = 0;
412 foreach ($arrayoflines as $line2) {
413 $alreadyproduced += $line2[
'qty'];
416 if ($alreadyproduced < $line->qty) {
417 $productioncomplete =
false;
422 $consumptioncomplete =
false;
423 $productioncomplete =
false;
427 dol_syslog(
"consumptioncomplete = ".json_encode($consumptioncomplete).
" productioncomplete = ".json_encode($productioncomplete));
428 if ($consumptioncomplete && $productioncomplete) {
429 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
431 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_MO_PRODUCED');
440 $action = str_replace(
'confirm_',
'', $action);
446 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
452 if ($action ==
'confirm_produced' && $confirm ==
'yes' && $permissiontoadd) {
453 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
457 $outputlangs = $langs;
460 $newlang =
GETPOST(
'lang_id',
'aZ09');
463 $newlang =
$object->thirdparty->default_lang;
465 if (!empty($newlang)) {
467 $outputlangs->setDefaultLang($newlang);
472 $object->generateDocument($model, $outputlangs, 0, 0, 0);
479 if ($action ==
'confirm_editline' && $permissiontoadd) {
480 $moline =
new MoLine($db);
483 $extrafields->fetch_name_optionals_label($moline->element);
484 foreach ($extrafields->attributes[$moline->table_element][
'label'] as $key => $label) {
485 $value =
GETPOST(
'options_'.$key,
'alphanohtml');
486 $moline->array_options[
"options_".$key] = $value;
489 $res = $moline->update($user);
492 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
495 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
507$form =
new Form($db);
514$title = $langs->trans(
'Mo');
515$help_url =
'EN:Module_Manufacturing_Orders|FR:Module_Ordres_de_Fabrication|DE:Modul_Fertigungsauftrag';
516$morejs = array(
'/mrp/js/lib_dispatch.js.php');
517llxHeader(
'', $title, $help_url,
'', 0, 0, $morejs,
'',
'',
'mod-mrp page-card_production');
522if (
$object->id > 0 && (empty($action) || ($action !=
'edit' && $action !=
'create'))) {
523 $res =
$object->fetch_thirdparty();
524 $res =
$object->fetch_optionals();
527 $tmpwarehouse->fetch(
$object->fk_warehouse);
528 $fk_default_warehouse =
$object->fk_warehouse;
538 if ($action ==
'delete') {
539 $formquestion = array(
541 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
542 'name' =>
'alsoCancelConsumedAndProducedLines',
543 'type' =>
'checkbox',
547 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'DeleteMo'), $langs->trans(
'ConfirmDeleteMo'),
'confirm_delete', $formquestion, 0, 1);
550 if ($action ==
'deleteline') {
551 $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);
554 if ($action ==
'clone') {
556 $formquestion = array();
557 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'ToClone'), $langs->trans(
'ConfirmCloneMo',
$object->ref),
'confirm_clone', $formquestion,
'yes', 1);
561 if ($action ==
'validate') {
563 $ref = substr(
$object->ref, 1, 4);
564 if ($ref ==
'PROV') {
571 $text = $langs->trans(
'ConfirmValidateMo', $numref);
580 $formquestion = array();
581 if (isModEnabled(
'mrp')) {
583 require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
586 if ($conf->browser->name ==
'ie') {
589 $formquestion = array(
596 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'Validate'), $text,
'confirm_validate', $formquestion, 0, 1, 220);
600 if ($action ==
'cancel') {
601 $formquestion = array(
603 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
604 'name' =>
'alsoCancelConsumedAndProducedLines',
605 'type' =>
'checkbox',
606 'value' => !
getDolGlobalString(
'MO_ALSO_CANCEL_CONSUMED_AND_PRODUCED_LINES_BY_DEFAULT') ? 0 : 1
609 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"] .
'?id=' .
$object->id, $langs->trans(
'CancelMo'), $langs->trans(
'ConfirmCancelMo'),
'confirm_cancel', $formquestion, 0, 1);
613 $parameters = array(
'formConfirm' => $formconfirm,
'lineid' => $lineid);
614 $reshook = $hookmanager->executeHooks(
'formConfirm', $parameters, $object, $action);
615 if (empty($reshook)) {
616 $formconfirm .= $hookmanager->resPrint;
617 } elseif ($reshook > 0) {
618 $formconfirm = $hookmanager->resPrint;
627 $linkback =
'<a href="'.DOL_URL_ROOT.
'/mrp/mo_list.php?restore_lastsearch_values=1'.(!empty($socid) ?
'&socid='.$socid :
'').
'">'.$langs->trans(
"BackToList").
'</a>';
629 $morehtmlref =
'<div class="refidno">';
638 if (is_object(
$object->thirdparty)) {
639 $morehtmlref .=
$object->thirdparty->getNomUrl(1,
'customer');
641 $morehtmlref .=
' (<a href="'.DOL_URL_ROOT.
'/commande/list.php?socid='.
$object->thirdparty->id.
'&search_societe='.urlencode(
$object->thirdparty->name).
'">'.$langs->trans(
"OtherOrders").
'</a>)';
646 if (isModEnabled(
'project')) {
647 $langs->load(
"projects");
648 if (is_object(
$object->thirdparty)) {
649 $morehtmlref .=
'<br>';
651 if ($permissiontoadd) {
652 $morehtmlref .=
img_picto($langs->trans(
"Project"),
'project',
'class="pictofixedwidth"');
653 if ($action !=
'classify') {
654 $morehtmlref .=
'<a class="editfielda" href="'.$_SERVER[
'PHP_SELF'].
'?action=classify&token='.
newToken().
'&id='.
$object->id.
'">'.
img_edit($langs->transnoentitiesnoconv(
'SetProject')).
'</a> ';
656 $morehtmlref .= $form->form_project($_SERVER[
'PHP_SELF'].
'?id='.
$object->id,
$object->socid,
$object->fk_project, ($action ==
'classify' ?
'projectid' :
'none'), 0, 0, 0, 1,
'',
'maxwidth300');
658 if (!empty(
$object->fk_project)) {
660 $proj->fetch(
$object->fk_project);
661 $morehtmlref .= $proj->getNomUrl(1);
663 $morehtmlref .=
'<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).
'</span>';
668 $morehtmlref .=
'</div>';
671 dol_banner_tab($object,
'ref', $linkback, 1,
'ref',
'ref', $morehtmlref);
674 print
'<div class="fichecenter">';
675 print
'<div class="fichehalfleft">';
676 print
'<div class="underbanner clearboth"></div>';
677 print
'<table class="border centpercent tableforfield">'.
"\n";
680 $keyforbreak =
'fk_warehouse';
681 unset(
$object->fields[
'fk_project']);
682 unset(
$object->fields[
'fk_soc']);
683 include DOL_DOCUMENT_ROOT.
'/core/tpl/commonfields_view.tpl.php';
686 include DOL_DOCUMENT_ROOT.
'/core/tpl/extrafields_view.tpl.php';
692 print
'<div class="clearboth"></div>';
697 if (!in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
698 print
'<div class="tabsAction">';
700 $parameters = array();
702 $reshook = $hookmanager->executeHooks(
'addMoreActionsButtons', $parameters, $object, $action);
703 if (empty($reshook)) {
705 if (
$object->status == $object::STATUS_DRAFT) {
706 if ($permissiontoadd) {
708 print
'<a class="butAction" href="'.$_SERVER[
'PHP_SELF'].
'?id='.
$object->id.
'&action=validate&token='.$newToken.
'">'.$langs->trans(
"Validate").
'</a>';
710 $langs->load(
"errors");
711 print
'<a class="butActionRefused" href="" title="'.$langs->trans(
"ErrorAddAtLeastOneLineFirst").
'">'.$langs->trans(
"Validate").
'</a>';
717 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
718 if ($permissiontoproduce) {
719 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeorproduce&token='.$newToken.
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
721 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
723 } elseif (
$object->status == Mo::STATUS_DRAFT) {
724 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
728 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
729 if ($permissiontoproduce) {
730 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeandproduceall&token='.$newToken.
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
732 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
734 } elseif (
$object->status == Mo::STATUS_DRAFT) {
735 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
739 if ($permissiontoadd) {
740 if (
$object->status == $object::STATUS_VALIDATED ||
$object->status == $object::STATUS_INPROGRESS) {
741 $arrayproduced =
$object->fetchLinesLinked(
'produced', 0);
743 foreach ($arrayproduced as $lineproduced) {
744 $nbProduced += $lineproduced[
'qty'];
746 if ($nbProduced > 0) {
747 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_produced&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
749 print
'<a class="butActionRefused" href="#" title="'.$langs->trans(
"GoOnTabProductionToProduceFirst", $langs->transnoentitiesnoconv(
"Production")).
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
752 print
'<a class="butActionDelete" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=cancel&token='.$newToken.
'">'.$langs->trans(
"Cancel").
'</a>'.
"\n";
755 if (
$object->status == $object::STATUS_CANCELED) {
756 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"ReOpen").
'</a>'.
"\n";
759 if (
$object->status == $object::STATUS_PRODUCED) {
760 if ($permissiontoproduce) {
761 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&token='.$newToken.
'">'.$langs->trans(
'ReOpen').
'</a>';
763 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ReOpen').
'</a>';
772 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline',
'addproduceline',
'editline'))) {
773 print
'<form method="POST" action="'.$_SERVER[
"PHP_SELF"].
'">';
774 print
'<input type="hidden" name="token" value="'.newToken().
'">';
775 print
'<input type="hidden" name="action" value="confirm_'.$action.
'">';
776 print
'<input type="hidden" name="backtopage" value="'.$backtopage.
'">';
777 print
'<input type="hidden" name="id" value="'.$id.
'">';
780 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
781 $defaultstockmovementlabel =
GETPOST(
'inventorylabel',
'alphanohtml') ?
GETPOST(
'inventorylabel',
'alphanohtml') : $langs->trans(
"ProductionForRef",
$object->
ref);
784 print
'<div class="center'.(in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) ?
' formconsumeproduce' :
'').
'">';
785 print
'<div class="opacitymedium hideonsmartphone paddingbottom">'.$langs->trans(
"ConfirmProductionDesc", $langs->transnoentitiesnoconv(
"Confirm")).
'<br></div>';
786 print
'<span class="fieldrequired">'.$langs->trans(
"InventoryCode").
':</span> <input type="text" class="minwidth150 maxwidth200" name="inventorycode" value="'.$defaultstockmovementcode.
'"> ';
787 print
'<span class="clearbothonsmartphone"></span>';
788 print $langs->trans(
"MovementLabel").
': <input type="text" class="minwidth300" name="inventorylabel" value="'.$defaultstockmovementlabel.
'"><br><br>';
789 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>';
790 print
'<input type="submit" class="button" value="'.$langs->trans(
"Confirm").
'" name="confirm">';
792 print
'<input class="button button-cancel" type="submit" value="'.$langs->trans(
"Cancel").
'" name="cancel">';
806 if (!empty(
$object->table_element_line)) {
813 $res = $bom->fetch(
$object->fk_bom);
815 $bom->calculateCosts();
816 $bomcost = $bom->unit_cost;
822 print
'<!-- Lines to consume -->'.
"\n";
823 print
'<div class="fichecenter">';
824 print
'<div class="fichehalfleft">';
825 print
'<div class="clearboth"></div>';
827 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addconsumeline&token='.
newToken();
828 $permissiontoaddaconsumeline = (
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED) ? 1 : -2;
829 $parameters = array(
'morecss' =>
'reposition');
831 if ($permissiontoaddaconsumeline == -2) {
832 $helpText = $langs->trans(
'MOIsClosed');
836 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
837 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewConsumeLines'), $helpText,
'fa fa-plus-circle size15x', $url,
'', $permissiontoaddaconsumeline, $parameters);
840 print
load_fiche_titre($langs->trans(
'Consumption'), $newcardbutton,
'', 0,
'',
'',
'');
842 print
'<div class="div-table-responsive-no-min">';
843 print
'<table class="noborder noshadow centpercent nobottom">';
845 print
'<!-- Line of title for products to consume -->'.
"\n";
846 print
'<tr class="liste_titre">';
848 print
'<td>'.$langs->trans(
"Product").
'</td>';
850 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
855 print
'<td class="right">'.$langs->trans(
"UnitCost").
'</td>';
858 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyConsumedShort"), $langs->trans(
"QtyAlreadyConsumed")).
'</td>';
861 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
862 print $langs->trans(
"Warehouse");
863 if (isModEnabled(
'workstation')) {
864 print
' '.$langs->trans(
"or").
' '.$langs->trans(
"Workstation");
867 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
868 $listwarehouses = $tmpwarehouse->list_array(1);
869 if (count($listwarehouses) > 1) {
870 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, $langs->trans(
"ForceTo"), 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
871 } elseif (count($listwarehouses) == 1) {
872 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
878 if (isModEnabled(
'stock')) {
880 print
'<td align="right">';
881 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
882 print $langs->trans(
"Stock");
887 if (isModEnabled(
'productbatch')) {
889 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
890 print $langs->trans(
"Batch");
902 if (
$object->status == Mo::STATUS_DRAFT) {
907 if ($permissiontodelete) {
913 if ($action ==
'addconsumeline') {
914 print
'<!-- Add line to consume -->'.
"\n";
915 print
'<tr class="liste_titre">';
918 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth150');
921 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width40 right"></td>';
930 if (isModEnabled(
'stock')) {
933 if (isModEnabled(
'productbatch')) {
937 print
'<td colspan="'.$colspan.
'">';
938 print
'<input type="submit" class="button buttongen button-add" name="addconsumelinebutton" value="'.$langs->trans(
"Add").
'">';
939 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdconsumelinebutton" value="'.$langs->trans(
"Cancel").
'">';
944 if (
$object->status == Mo::STATUS_DRAFT) {
948 if ($permissiontodelete) {
954 if (is_object($objectline)) {
955 $extrafields->fetch_name_optionals_label(
$object->table_element_line);
956 $temps = $objectline->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
957 if (!empty($temps)) {
958 print
'<tr class="liste_titre"><td style="padding-top: 20px" colspan="9" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
970 $nblinetoconsume = 0;
971 foreach (
$object->lines as $line) {
972 if ($line->role ==
'toconsume') {
977 $nblinetoconsumecursor = 0;
978 foreach (
$object->lines as $line) {
979 if ($line->role ==
'toconsume') {
980 $nblinetoconsumecursor++;
982 $tmpproduct =
new Product($db);
983 $tmpproduct->fetch($line->fk_product);
984 $linecost =
price2num($tmpproduct->pmp,
'MT');
988 $costprice =
price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp);
989 if (empty($costprice)) {
990 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
992 if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) {
993 $costprice = $productFournisseur->fourn_unitprice;
1001 if ($useunit && $line->fk_unit > 0) {
1003 $qtyhourservice = 0;
1004 if (preg_match(
'/^(\d+)([a-z]+)$/', $tmpproduct->duration, $reg)) {
1007 $qtyhourforline = 0;
1008 if ($line->fk_unit) {
1013 if ($qtyhourservice && $qtyhourforline) {
1014 $linecost =
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MT');
1015 $bomcostupdated +=
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MU');
1018 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1022 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1026 $bomcostupdated =
price2num($bomcostupdated,
'MU');
1027 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1028 $alreadyconsumed = 0;
1029 foreach ($arrayoflines as $line2) {
1030 $alreadyconsumed += $line2[
'qty'];
1033 if ($action ==
'editline' && $lineid == $line->id) {
1034 $linecost =
price2num($tmpproduct->pmp,
'MT');
1036 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1037 $alreadyconsumed = 0;
1038 if (is_array($arrayoflines) && !empty($arrayoflines)) {
1039 foreach ($arrayoflines as $line2) {
1040 $alreadyconsumed += $line2[
'qty'];
1043 $suffix =
'_' . $line->id;
1044 print
'<!-- Line to dispatch ' . $suffix .
' (line edited) -->' .
"\n";
1046 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1048 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1050 print
'<input name="lineid" type="hidden" value="' . $line->id .
'">';
1053 print
'<td>' . $tmpproduct->getNomUrl(1);
1054 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</span>';
1058 print
'<td class="right nowraponall">';
1059 print
'<input class="width40 right" name="qty_lineProduce" value="'. $line->qty.
'">';
1063 print
'<td class="right nowraponall">';
1071 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1076 print
'<td class="right">';
1077 print
' ' .
price2num($alreadyconsumed,
'MS');
1085 if (isModEnabled(
'stock')) {
1086 print
'<td class="nowraponall right">';
1087 if ($tmpproduct->isStockManaged()) {
1088 if ($tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1089 print
img_warning($langs->trans(
'StockTooLow')).
' ';
1091 print
'<span class="left">'. $tmpproduct->stock_reel .
' </span>';
1097 if (isModEnabled(
'productbatch')) {
1101 print
'<td colspan="'.(3 + (
$object->status == Mo::STATUS_DRAFT ? 1 : 0) + ($permissiontodelete ? 1 : 0)).
'">';
1102 print
'<input type="submit" class="button buttongen button-add small nominwidth" name="save" value="' . $langs->trans(
"Save") .
'">';
1103 print
'<input type="submit" class="button buttongen button-cancel small nominwidth" name="cancel" value="' . $langs->trans(
"Cancel") .
'">';
1109 if (!empty($extrafields)) {
1110 $line->fetch_optionals();
1111 $temps = $line->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
1112 if (!empty($temps)) {
1114 print
'<tr><td colspan="'.$colspan.
'"><div style="padding-top: 20px" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
1116 print
'</div></td></tr>';
1120 $suffix =
'_' . $line->id;
1121 print
'<!-- Line to dispatch ' . $suffix .
' -->' .
"\n";
1123 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1124 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1126 print
'<tr data-line-id="' . $line->id .
'">';
1129 print
'<td>' . $tmpproduct->getNomUrl(1);
1130 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</div>';
1134 print
'<td class="right nowraponall">';
1136 if ($line->qty_frozen) {
1137 $help = ($help ?
'<br>' :
'') .
'<strong>' . $langs->trans(
"QuantityFrozen") .
'</strong>: ' .
yn(1) .
' (' . $langs->trans(
"QuantityConsumedInvariable") .
')';
1138 print $form->textwithpicto(
'', $help, -1,
'lock') .
' ';
1140 if ($line->disable_stock_change) {
1141 $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")) .
')';
1142 print $form->textwithpicto(
'', $help, -1,
'help') .
' ';
1148 print
'<td class="right nowraponall">';
1156 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1157 print
'<td class="right nowraponall">';
1158 print
price($linecost);
1163 print
'<td class="right">';
1164 if ($alreadyconsumed) {
1166 print
'jQuery(document).ready(function() {
1167 jQuery("#expandtoproduce' . $line->id .
'").click(function() {
1168 console.log("Expand mrp_production line ' . $line->id .
'");
1169 jQuery(".expanddetail' . $line->id .
'").toggle();';
1170 if ($nblinetoconsume == $nblinetoconsumecursor) {
1171 print
'if (jQuery("#tablelines").hasClass("nobottom")) { jQuery("#tablelines").removeClass("nobottom"); } else { jQuery("#tablelines").addClass("nobottom"); }';
1177 if (empty($conf->use_javascript_ajax)) {
1178 print
'<a href="' . $_SERVER[
"PHP_SELF"] .
'?collapse=' . $collapse .
',' . $line->id .
'">';
1180 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce' . $line->id .
'"');
1181 if (empty($conf->use_javascript_ajax)) {
1185 if ($nblinetoconsume == $nblinetoconsumecursor) {
1186 print
'<script>jQuery("#tablelines").removeClass("nobottom");</script>';
1189 print
' ' .
price2num($alreadyconsumed,
'MS');
1194 if (
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') && $tmpwarehouse->id > 0) {
1195 print
img_picto(
'', $tmpwarehouse->picto) .
" " . $tmpwarehouse->label;
1197 if (isModEnabled(
'workstation') && $line->fk_default_workstation > 0) {
1199 $tmpworkstation->fetch($line->fk_default_workstation);
1200 print $tmpworkstation->getNomUrl(1);
1205 if (isModEnabled(
'stock')) {
1206 print
'<td class="nowraponall right">';
1208 if (!$line->disable_stock_change && $tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1209 print
img_warning($langs->trans(
'StockTooLow')) .
' ';
1211 if (!
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') || empty($tmpwarehouse->id)) {
1212 print
price2num($tmpproduct->stock_reel,
'MS');
1215 $tmpproduct->load_stock();
1216 $wh_stock = $tmpproduct->stock_warehouse[$tmpwarehouse->id];
1217 if (!empty($wh_stock)) {
1228 if (isModEnabled(
'productbatch')) {
1239 if (
$object->status == Mo::STATUS_DRAFT) {
1240 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1241 print
'<td class="center">';
1242 print
'<a class="reposition editfielda" href="' . $href .
'">';
1243 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1249 if ($permissiontodelete) {
1250 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=deleteline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1251 print
'<td class="center">';
1252 print
'<a class="reposition" href="' . $href .
'">';
1253 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1261 if (!empty($extrafields)) {
1262 $line->fetch_optionals();
1263 $temps = $line->showOptionals($extrafields,
'view', array(),
'',
'', 1,
'line');
1264 if (!empty($temps)) {
1266 print
'<tr><td colspan="'.$colspan.
'"><div id="extrafield_lines_area_'.$line->id.
'" name="extrafield_lines_area_'.$line->id.
'">';
1268 print
'</div></td></tr>';
1274 foreach ($arrayoflines as $line2) {
1275 print
'<tr class="expanddetail'.$line->id.
' hideobject opacitylow">';
1279 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1280 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1291 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1296 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1299 print
'<td class="tdoverflowmax150">';
1300 if ($line2[
'fk_warehouse'] > 0) {
1301 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1303 print $tmpwarehouse->getNomUrl(1);
1309 if (isModEnabled(
'stock')) {
1314 if (isModEnabled(
'productbatch')) {
1316 if ($line2[
'batch'] !=
'') {
1317 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1318 print $tmpbatch->getNomUrl(1);
1330 if (
$object->status == Mo::STATUS_DRAFT) {
1331 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line2[
'rowid']);
1332 print
'<td class="center">';
1333 print
'<a class="reposition" href="' . $href .
'">';
1334 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1340 if ($permissiontodelete) {
1341 $href = $_SERVER[
"PHP_SELF"].
'?id='.((int)
$object->id).
'&action=deleteline&token='.
newToken().
'&lineid='.((int) $line2[
'rowid']).
'&fk_movement='.((int) $line2[
'fk_stock_movement']);
1342 print
'<td class="center">';
1343 print
'<a class="reposition" href="'.$href.
'">';
1344 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1352 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1354 print
'<!-- Enter line to consume -->'.
"\n";
1356 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1358 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToConsume").
'</span></td>';
1359 $preselected = (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i) ?
GETPOST(
'qty-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyconsumed));
1360 if ($action ==
'consumeorproduce' && !
getDolGlobalString(
'MRP_AUTO_SET_REMAINING_QUANTITIES_TO_BE_CONSUMED') && !GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
1365 if (
getDolGlobalString(
'MRP_NEVER_CONSUME_MORE_THAN_EXPECTED') && ($line->qty - $alreadyconsumed) <= 0) {
1366 $disable =
'disabled';
1370 print
'<input type="hidden" name="product-'.$line->id.
'-'.$i.
'" value="'.$line->fk_product.
'">';
1373 print
'<td class="right"><input type="text" class="width50 right" id="qtytoconsume-' . $line->id .
'-' . $i .
'" name="qty-' . $line->id .
'-' . $i .
'" value="' . $preselected .
'" ' . $disable .
'></td>';
1379 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1389 if (empty($line->disable_stock_change)) {
1390 $preselected = (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) : ($tmpproduct->fk_default_warehouse > 0 ? $tmpproduct->fk_default_warehouse :
'ifone'));
1391 print $formproduct->selectWarehouses($preselected,
'idwarehouse-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0, array(),
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1393 print
'<span class="opacitymedium">'.$langs->trans(
"DisableStockChange").
'</span>';
1396 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1401 if (isModEnabled(
'stock')) {
1406 if (isModEnabled(
'productbatch')) {
1407 print
'<td class="nowraponall">';
1408 if ($tmpproduct->status_batch) {
1409 $preselected = (GETPOSTISSET(
'batch-'.$line->id.
'-'.$i) ?
GETPOST(
'batch-'.$line->id.
'-'.$i) :
'');
1410 print
'<input type="text" class="width75" name="batch-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'" list="batch-'.$line->id.
'-'.$i.
'">';
1411 print $formproduct->selectLotDataList(
'batch-'.$line->id.
'-'.$i, 0, $line->fk_product, 0, array());
1418 print
'<td align="right" class="split">';
1419 print
' '.img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.((int) $line->id).
', \''.
dol_escape_js($type).
'\', \
'qtymissingconsume\')"');
1423 print
'<td align="right" class="splitall">';
1424 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1425 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" data-max-qty="1" onClick="addDispatchLine('.$line->id.
', \'batch\', \'allmissingconsume\')"');
1430 if (
$object->status == Mo::STATUS_DRAFT) {
1435 if ($permissiontodelete) {
1449 print
'<script type="text/javascript">
1450 $(document).ready(function () {
1451 $("select[name=fk_default_warehouse]").change(function() {
1452 var fk_default_warehouse = $("option:selected", this).val();
1453 $("select[name^=idwarehouse-]").val(fk_default_warehouse).change();
1458 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) &&
1460 print
'<script>$(document).ready(function () {
1461 $("#fk_default_warehouse").change();
1469 print
'<div class="fichehalfright">';
1470 print
'<div class="clearboth"></div>';
1472 $nblinetoproduce = 0;
1473 foreach (
$object->lines as $line) {
1474 if ($line->role ==
'toproduce') {
1479 $newcardbutton =
'';
1480 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addproduceline&token='.
newToken();
1481 $permissiontoaddaproductline =
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED;
1482 $parameters = array(
'morecss' =>
'reposition');
1483 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
1484 if ($nblinetoproduce == 0 ||
$object->mrptype == 1) {
1485 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewProduceLines'),
'',
'fa fa-plus-circle size15x', $url,
'', (
int) $permissiontoaddaproductline, $parameters);
1489 print
load_fiche_titre($langs->trans(
'Production'), $newcardbutton,
'', 0,
'',
'');
1491 print
'<div class="div-table-responsive-no-min">';
1492 print
'<table id="tablelinestoproduce" class="noborder noshadow nobottom centpercent">';
1494 print
'<tr class="liste_titre">';
1496 print
'<td>'.$langs->trans(
"Product").
'</td>';
1498 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
1501 print
'<td class="right">'.$langs->trans(
"Unit").
'</td>';
1504 if ($permissiontoupdatecost) {
1505 if (empty($bomcostupdated)) {
1506 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"UnitCost"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1508 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"ManufacturingPrice"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1512 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyProducedShort"), $langs->trans(
"QtyAlreadyProduced")).
'</td>';
1515 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1516 print $langs->trans(
"Warehouse");
1521 if (isModEnabled(
'productbatch')) {
1523 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1524 print $langs->trans(
"Batch");
1536 if ($permissiontodelete) {
1542 if ($action ==
'addproduceline') {
1543 print
'<!-- Add line to produce -->'.
"\n";
1544 print
'<tr class="liste_titre">';
1548 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
1551 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
1557 if ($permissiontoupdatecost) {
1561 print
'<td colspan="2">';
1562 print
'<input type="submit" class="button buttongen button-add" name="addproducelinebutton" value="'.$langs->trans(
"Add").
'">';
1563 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdproducelinebutton" value="'.$langs->trans(
"Cancel").
'">';
1566 if (isModEnabled(
'productbatch')) {
1576 if ($permissiontodelete) {
1583 $nblinetoproduce = 0;
1584 foreach (
$object->lines as $line) {
1585 if ($line->role ==
'toproduce') {
1590 $nblinetoproducecursor = 0;
1591 foreach (
$object->lines as $line) {
1592 if ($line->role ==
'toproduce') {
1595 $nblinetoproducecursor++;
1597 $tmpproduct =
new Product($db);
1598 $tmpproduct->fetch($line->fk_product);
1600 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
1601 $alreadyproduced = 0;
1602 foreach ($arrayoflines as $line2) {
1603 $alreadyproduced += $line2[
'qty'];
1606 $suffix =
'_'.$line->id;
1607 print
'<!-- Line to dispatch '.$suffix.
' (toproduce) -->'.
"\n";
1609 print
'<input id="qty_ordered'.$suffix.
'" type="hidden" value="'.$line->qty.
'">';
1610 print
'<input id="qty_dispatched'.$suffix.
'" type="hidden" value="'.$alreadyproduced.
'">';
1614 print
'<td>'.$tmpproduct->getNomUrl(1);
1615 print
'<br><span class="opacitymedium small">'.$tmpproduct->label.
'</span>';
1618 print
'<td class="right">'.$line->qty.
'</td>';
1621 print
'<td class="right">'.measuringUnitString($line->fk_unit,
'',
'', 1).
'</td>';
1624 if ($permissiontoupdatecost) {
1626 $manufacturingcost = 0;
1627 $manufacturingcostsrc =
'';
1629 $manufacturingcost = $bomcostupdated;
1630 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1631 if (empty($manufacturingcost)) {
1632 $manufacturingcost = $bomcost;
1633 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1635 if (empty($manufacturingcost)) {
1636 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1637 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1639 if (empty($manufacturingcost)) {
1640 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1641 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1645 print
'<td class="right nowraponall" title="'.dol_escape_htmltag($manufacturingcostsrc).
'">';
1646 if ($manufacturingcost) {
1647 print
price($manufacturingcost);
1652 print
'<td class="right nowraponall">';
1653 if ($alreadyproduced) {
1655 print
'jQuery(document).ready(function() {
1656 jQuery("#expandtoproduce'.$line->id.
'").click(function() {
1657 console.log("Expand mrp_production line '.$line->id.
'");
1658 jQuery(".expanddetailtoproduce'.$line->id.
'").toggle();';
1659 if ($nblinetoproduce == $nblinetoproducecursor) {
1660 print
'if (jQuery("#tablelinestoproduce").hasClass("nobottom")) { jQuery("#tablelinestoproduce").removeClass("nobottom"); } else { jQuery("#tablelinestoproduce").addClass("nobottom"); }';
1666 if (empty($conf->use_javascript_ajax)) {
1667 print
'<a href="'.$_SERVER[
"PHP_SELF"].
'?collapse='.$collapse.
','.$line->id.
'">';
1669 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce'.$line->id.
'"');
1670 if (empty($conf->use_javascript_ajax)) {
1674 print
' '.$alreadyproduced;
1680 if (isModEnabled(
'productbatch')) {
1690 if ($permissiontodelete) {
1691 if ($line->origin_type ==
'free') {
1692 $href = $_SERVER[
"PHP_SELF"];
1693 $href .=
'?id='.$object->id;
1694 $href .=
'&action=deleteline';
1695 $href .=
'&lineid='.$line->id;
1696 print
'<td class="center">';
1697 print
'<a class="reposition" href="'.$href.
'">';
1698 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
"delete");
1708 foreach ($arrayoflines as $line2) {
1709 print
'<tr class="expanddetailtoproduce'.$line->id.
' hideobject opacitylow">';
1712 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1713 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1723 if ($permissiontoupdatecost) {
1727 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1729 print
'<td class="tdoverflowmax150">';
1730 if ($line2[
'fk_warehouse'] > 0) {
1731 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1733 print $tmpwarehouse->getNomUrl(1);
1738 if (isModEnabled(
'productbatch')) {
1740 if ($line2[
'batch'] !=
'') {
1741 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1742 print $tmpbatch->getNomUrl(1);
1753 if ($permissiontodelete) {
1759 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1760 print
'<!-- Enter line to produce -->'.
"\n";
1762 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1764 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToProduce").
'</span></td>';
1765 $preselected = (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyproduced));
1766 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
1770 print
'<td class="right"><input type="text" class="width50 right" id="qtytoproduce-'.$line->id.
'-'.$i.
'" name="qtytoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1773 print
'<td class="right"></td>';
1776 if ($permissiontoupdatecost) {
1778 $manufacturingcost = 0;
1779 $manufacturingcostsrc =
'';
1781 $manufacturingcost = $bomcostupdated;
1782 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1783 if (empty($manufacturingcost)) {
1784 $manufacturingcost = $bomcost;
1785 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1787 if (empty($manufacturingcost)) {
1788 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1789 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1791 if (empty($manufacturingcost)) {
1792 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1793 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1798 $preselected = (GETPOSTISSET(
'pricetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) : ($manufacturingcost ?
price($manufacturingcost) :
''));
1799 print
'<td class="right"><input type="text" class="width75 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1801 print
'<td><input type="hidden" class="width50 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.($manufacturingcost ? $manufacturingcost :
'').
'"></td>';
1809 $preselected = (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) : (
$object->fk_warehouse > 0 ?
$object->fk_warehouse :
'ifone'));
1810 print $formproduct->selectWarehouses($preselected,
'idwarehousetoproduce-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0, array(),
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1812 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1816 if (isModEnabled(
'productbatch')) {
1818 if ($tmpproduct->status_batch) {
1819 $preselected = (GETPOSTISSET(
'batchtoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i) :
'');
1820 print
'<input type="text" class="width75" name="batchtoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'">';
1824 if ($tmpproduct->status_batch) {
1826 print
'<td align="right" class="split">';
1827 print
img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.$line->id.
', \''.$type.
'\', \
'qtymissing\')"');
1830 print
'<td align="right" class="splitall">';
1831 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1832 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" onClick="addDispatchLine('.$line->id.
', \'batch\', \'alltoproduce\')"');
1858 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline'))) {
1862 <script
type=
"text/javascript" language=
"javascript">
1864 $(document).ready(
function() {
1866 updateselectbatchbywarehouse();
1868 updateselectwarehousebybatch();
1871 function updateselectbatchbywarehouse() {
1872 $(document).on(
'change',
"select[name*='idwarehouse']",
function () {
1873 console.log(
"We change warehouse so we update the list of possible batch number");
1875 var selectwarehouse = $(
this);
1877 var selectbatch_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'batch');
1878 var selectbatch = $(
"datalist[id*='" + selectbatch_name +
"']");
1879 var selectedbatch = selectbatch.val();
1881 var product_element_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'product');
1885 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1887 action:
"updateselectbatchbywarehouse",
1888 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1889 warehouse_id: $(
this).val(),
1890 token:
'<?php echo currentToken(); ?>',
1891 product_id: $(
"input[name='" + product_element_name +
"']").val()
1893 }).done(
function (data) {
1895 selectbatch.empty();
1897 if (typeof data ==
"object") {
1898 console.log(
"data is already type object, no need to parse it");
1900 console.log(
"data is type "+(typeof data));
1901 data = JSON.parse(data);
1904 selectbatch.append($(
'<option>', {
1908 $.each(data,
function (key, value) {
1910 if(selectwarehouse.val() == -1) {
1911 var label = key +
" (<?php echo $langs->trans('Stock total') ?> : " + value +
")";
1913 var label = key +
" (<?php echo $langs->trans('Stock') ?> : " + value +
")";
1916 if(key === selectedbatch) {
1917 var option =
'<option value="'+key+
'" selected>'+ label +
'</option>';
1919 var option =
'<option value="'+key+
'">'+ label +
'</option>';
1922 selectbatch.append(option);
1928 function updateselectwarehousebybatch() {
1929 $(document).on(
'change',
'input[name*=batch]',
function(){
1930 console.log(
"We change batch so we update the list of possible warehouses");
1932 var selectbatch = $(
this);
1934 var selectwarehouse_name = selectbatch.attr(
'name').replace(
'batch',
'idwarehouse');
1935 var selectwarehouse = $(
"select[name*='" + selectwarehouse_name +
"']");
1936 var selectedwarehouse = selectwarehouse.val();
1938 if(selectedwarehouse != -1){
1942 var product_element_name = selectbatch.attr(
'name').replace(
'batch',
'product');
1946 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1948 action:
"updateselectwarehousebybatch",
1949 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1950 batch: $(
this).val(),
1951 token:
'<?php echo currentToken(); ?>',
1952 product_id: $(
"input[name='" + product_element_name +
"']").val()
1954 }).done(
function (data) {
1956 if (typeof data ==
"object") {
1957 console.log(
"data is already type object, no need to parse it");
1959 console.log(
"data is type "+(typeof data));
1960 data = JSON.parse(data);
1964 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.
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...
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.