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'),
'',
'',
'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
'<tr class="liste_titre">';
847 print
'<td>'.$langs->trans(
"Product").
'</td>';
849 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
854 print
'<td class="right">'.$langs->trans(
"UnitCost").
'</td>';
857 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyConsumedShort"), $langs->trans(
"QtyAlreadyConsumed")).
'</td>';
860 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
861 print $langs->trans(
"Warehouse");
862 if (isModEnabled(
'workstation')) {
863 print
' '.$langs->trans(
"or").
' '.$langs->trans(
"Workstation");
866 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
867 $listwarehouses = $tmpwarehouse->list_array(1);
868 if (count($listwarehouses) > 1) {
869 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, $langs->trans(
"ForceTo"), 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
870 } elseif (count($listwarehouses) == 1) {
871 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
877 if (isModEnabled(
'stock')) {
879 print
'<td align="right">';
880 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
881 print $langs->trans(
"Stock");
886 if (isModEnabled(
'productbatch')) {
888 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
889 print $langs->trans(
"Batch");
894 if ($permissiontodelete) {
905 if (
$object->status == Mo::STATUS_DRAFT) {
911 if ($action ==
'addconsumeline') {
912 print
'<!-- Add line to consume -->'.
"\n";
913 print
'<tr class="liste_titre">';
916 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
919 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
927 print
'<td colspan="2">';
928 print
'<input type="submit" class="button buttongen button-add" name="addconsumelinebutton" value="'.$langs->trans(
"Add").
'">';
929 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdconsumelinebutton" value="'.$langs->trans(
"Cancel").
'">';
931 if (isModEnabled(
'stock')) {
935 if (isModEnabled(
'productbatch')) {
939 if ($permissiontodelete) {
947 if (
$object->status == Mo::STATUS_DRAFT) {
953 if (is_object($objectline)) {
954 $extrafields->fetch_name_optionals_label(
$object->table_element_line);
955 $temps = $objectline->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
956 if (!empty($temps)) {
957 print
'<tr class="liste_titre"><td style="padding-top: 20px" colspan="9" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
969 $nblinetoconsume = 0;
970 foreach (
$object->lines as $line) {
971 if ($line->role ==
'toconsume') {
976 $nblinetoconsumecursor = 0;
977 foreach (
$object->lines as $line) {
978 if ($line->role ==
'toconsume') {
979 $nblinetoconsumecursor++;
981 $tmpproduct =
new Product($db);
982 $tmpproduct->fetch($line->fk_product);
983 $linecost =
price2num($tmpproduct->pmp,
'MT');
987 $costprice =
price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp);
988 if (empty($costprice)) {
989 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
991 if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) {
992 $costprice = $productFournisseur->fourn_unitprice;
1000 if ($useunit && $line->fk_unit > 0) {
1002 $qtyhourservice = 0;
1003 if (preg_match(
'/^(\d+)([a-z]+)$/', $tmpproduct->duration, $reg)) {
1006 $qtyhourforline = 0;
1007 if ($line->fk_unit) {
1012 if ($qtyhourservice && $qtyhourforline) {
1013 $linecost =
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MT');
1014 $bomcostupdated +=
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MU');
1017 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1021 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1025 $bomcostupdated =
price2num($bomcostupdated,
'MU');
1026 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1027 $alreadyconsumed = 0;
1028 foreach ($arrayoflines as $line2) {
1029 $alreadyconsumed += $line2[
'qty'];
1032 if ($action ==
'editline' && $lineid == $line->id) {
1033 $linecost =
price2num($tmpproduct->pmp,
'MT');
1035 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1036 $alreadyconsumed = 0;
1037 if (is_array($arrayoflines) && !empty($arrayoflines)) {
1038 foreach ($arrayoflines as $line2) {
1039 $alreadyconsumed += $line2[
'qty'];
1042 $suffix =
'_' . $line->id;
1043 print
'<!-- Line to dispatch ' . $suffix .
' (line edited) -->' .
"\n";
1045 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1047 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1049 print
'<input name="lineid" type="hidden" value="' . $line->id .
'">';
1052 print
'<td>' . $tmpproduct->getNomUrl(1);
1053 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</span>';
1057 print
'<td class="right nowraponall">';
1058 print
'<input class="width40 right" name="qty_lineProduce" value="'. $line->qty.
'">';
1062 print
'<td class="right nowraponall">';
1070 print
'<td class="right">';
1071 print
' ' .
price2num($alreadyconsumed,
'MS');
1079 print
'<td class="nowraponall right">';
1080 if ($tmpproduct->isStockManaged()) {
1081 if ($tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1082 print
img_warning($langs->trans(
'StockTooLow')).
' ';
1084 print
'<span class="left">'. $tmpproduct->stock_reel .
' </span>';
1095 print
'<td colspan="'.($permissiontodelete ? 4 : 3).
'">';
1096 print
'<input type="submit" class="button buttongen button-add small nominwidth" name="save" value="' . $langs->trans(
"Save") .
'">';
1097 print
'<input type="submit" class="button buttongen button-cancel small nominwidth" name="cancel" value="' . $langs->trans(
"Cancel") .
'">';
1103 if (!empty($extrafields)) {
1104 $line->fetch_optionals();
1105 $temps = $line->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
1106 if (!empty($temps)) {
1107 print
'<td colspan="10"><div style="padding-top: 20px" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
1109 print
'</div></td>';
1113 $suffix =
'_' . $line->id;
1114 print
'<!-- Line to dispatch ' . $suffix .
' -->' .
"\n";
1116 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1117 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1119 print
'<tr data-line-id="' . $line->id .
'">';
1122 print
'<td>' . $tmpproduct->getNomUrl(1);
1123 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</div>';
1127 print
'<td class="right nowraponall">';
1129 if ($line->qty_frozen) {
1130 $help = ($help ?
'<br>' :
'') .
'<strong>' . $langs->trans(
"QuantityFrozen") .
'</strong>: ' .
yn(1) .
' (' . $langs->trans(
"QuantityConsumedInvariable") .
')';
1131 print $form->textwithpicto(
'', $help, -1,
'lock') .
' ';
1133 if ($line->disable_stock_change) {
1134 $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")) .
')';
1135 print $form->textwithpicto(
'', $help, -1,
'help') .
' ';
1141 print
'<td class="right nowraponall">';
1149 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1150 print
'<td class="right nowraponall">';
1151 print
price($linecost);
1156 print
'<td class="right">';
1157 if ($alreadyconsumed) {
1159 print
'jQuery(document).ready(function() {
1160 jQuery("#expandtoproduce' . $line->id .
'").click(function() {
1161 console.log("Expand mrp_production line ' . $line->id .
'");
1162 jQuery(".expanddetail' . $line->id .
'").toggle();';
1163 if ($nblinetoconsume == $nblinetoconsumecursor) {
1164 print
'if (jQuery("#tablelines").hasClass("nobottom")) { jQuery("#tablelines").removeClass("nobottom"); } else { jQuery("#tablelines").addClass("nobottom"); }';
1170 if (empty($conf->use_javascript_ajax)) {
1171 print
'<a href="' . $_SERVER[
"PHP_SELF"] .
'?collapse=' . $collapse .
',' . $line->id .
'">';
1173 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce' . $line->id .
'"');
1174 if (empty($conf->use_javascript_ajax)) {
1178 if ($nblinetoconsume == $nblinetoconsumecursor) {
1179 print
'<script>jQuery("#tablelines").removeClass("nobottom");</script>';
1182 print
' ' .
price2num($alreadyconsumed,
'MS');
1186 if (
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') && $tmpwarehouse->id > 0) {
1187 print
img_picto(
'', $tmpwarehouse->picto) .
" " . $tmpwarehouse->label;
1189 if (isModEnabled(
'workstation') && $line->fk_default_workstation > 0) {
1191 $tmpworkstation->fetch($line->fk_default_workstation);
1192 print $tmpworkstation->getNomUrl(1);
1196 if (isModEnabled(
'stock')) {
1197 print
'<td class="nowraponall right">';
1199 if (!$line->disable_stock_change && $tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1200 print
img_warning($langs->trans(
'StockTooLow')) .
' ';
1202 if (!
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') || empty($tmpwarehouse->id)) {
1203 print
price2num($tmpproduct->stock_reel,
'MS');
1206 $tmpproduct->load_stock();
1207 $wh_stock = $tmpproduct->stock_warehouse[$tmpwarehouse->id];
1208 if (!empty($wh_stock)) {
1218 if (isModEnabled(
'productbatch')) {
1229 if (
$object->status == Mo::STATUS_DRAFT) {
1230 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1231 print
'<td class="center">';
1232 print
'<a class="reposition editfielda" href="' . $href .
'">';
1233 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1239 if ($permissiontodelete) {
1240 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=deleteline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1241 print
'<td class="center">';
1242 print
'<a class="reposition" href="' . $href .
'">';
1243 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1250 if (!empty($extrafields)) {
1251 $line->fetch_optionals();
1252 $temps = $line->showOptionals($extrafields,
'view', array(),
'',
'', 1,
'line');
1253 if (!empty($temps)) {
1254 print
'<td colspan="10"><div id="extrafield_lines_area_'.$line->id.
'" name="extrafield_lines_area_'.$line->id.
'">';
1256 print
'</div></td>';
1261 foreach ($arrayoflines as $line2) {
1262 print
'<tr class="expanddetail'.$line->id.
' hideobject opacitylow">';
1266 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1267 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1275 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1278 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1283 print
'<td class="tdoverflowmax150">';
1284 if ($line2[
'fk_warehouse'] > 0) {
1285 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1287 print $tmpwarehouse->getNomUrl(1);
1293 if (isModEnabled(
'stock')) {
1298 if (isModEnabled(
'productbatch')) {
1300 if ($line2[
'batch'] !=
'') {
1301 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1302 print $tmpbatch->getNomUrl(1);
1314 if (
$object->status == Mo::STATUS_DRAFT) {
1315 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line2[
'rowid']);
1316 print
'<td class="center">';
1317 print
'<a class="reposition" href="' . $href .
'">';
1318 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1324 if ($permissiontodelete) {
1325 $href = $_SERVER[
"PHP_SELF"].
'?id='.((int)
$object->id).
'&action=deleteline&token='.
newToken().
'&lineid='.((int) $line2[
'rowid']).
'&fk_movement='.((int) $line2[
'fk_stock_movement']);
1326 print
'<td class="center">';
1327 print
'<a class="reposition" href="'.$href.
'">';
1328 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1336 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1338 print
'<!-- Enter line to consume -->'.
"\n";
1340 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1342 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToConsume").
'</span></td>';
1343 $preselected = (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i) ?
GETPOST(
'qty-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyconsumed));
1344 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
1349 if (
getDolGlobalString(
'MRP_NEVER_CONSUME_MORE_THAN_EXPECTED') && ($line->qty - $alreadyconsumed) <= 0) {
1350 $disable =
'disabled';
1354 print
'<input type="hidden" name="product-'.$line->id.
'-'.$i.
'" value="'.$line->fk_product.
'">';
1357 print
'<td class="right"><input type="text" class="width50 right" id="qtytoconsume-' . $line->id .
'-' . $i .
'" name="qty-' . $line->id .
'-' . $i .
'" value="' . $preselected .
'" ' . $disable .
'></td>';
1365 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1375 if (empty($line->disable_stock_change)) {
1376 $preselected = (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) : ($tmpproduct->fk_default_warehouse > 0 ? $tmpproduct->fk_default_warehouse :
'ifone'));
1377 print $formproduct->selectWarehouses($preselected,
'idwarehouse-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0,
null,
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1379 print
'<span class="opacitymedium">'.$langs->trans(
"DisableStockChange").
'</span>';
1382 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1387 if (isModEnabled(
'stock')) {
1392 if (isModEnabled(
'productbatch')) {
1393 print
'<td class="nowraponall">';
1394 if ($tmpproduct->status_batch) {
1395 $preselected = (GETPOSTISSET(
'batch-'.$line->id.
'-'.$i) ?
GETPOST(
'batch-'.$line->id.
'-'.$i) :
'');
1396 print
'<input type="text" class="width75" name="batch-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'" list="batch-'.$line->id.
'-'.$i.
'">';
1397 print $formproduct->selectLotDataList(
'batch-'.$line->id.
'-'.$i, 0, $line->fk_product,
'',
'');
1404 print
'<td align="right" class="split">';
1405 print
' '.img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.((int) $line->id).
', \''.
dol_escape_js($type).
'\', \
'qtymissingconsume\')"');
1409 print
'<td align="right" class="splitall">';
1410 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1411 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" data-max-qty="1" onClick="addDispatchLine('.$line->id.
', \'batch\', \'allmissingconsume\')"');
1416 if (
$object->status == Mo::STATUS_DRAFT) {
1421 if ($permissiontodelete) {
1435 print
'<script type="text/javascript">
1436 $(document).ready(function () {
1437 $("select[name=fk_default_warehouse]").change(function() {
1438 var fk_default_warehouse = $("option:selected", this).val();
1439 $("select[name^=idwarehouse-]").val(fk_default_warehouse).change();
1444 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) &&
1446 print
'<script>$(document).ready(function () {
1447 $("#fk_default_warehouse").change();
1455 print
'<div class="fichehalfright">';
1456 print
'<div class="clearboth"></div>';
1458 $nblinetoproduce = 0;
1459 foreach (
$object->lines as $line) {
1460 if ($line->role ==
'toproduce') {
1465 $newcardbutton =
'';
1466 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addproduceline&token='.
newToken();
1467 $permissiontoaddaproductline =
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED;
1468 $parameters = array(
'morecss' =>
'reposition');
1469 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
1470 if ($nblinetoproduce == 0 ||
$object->mrptype == 1) {
1471 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewProduceLines'),
'',
'fa fa-plus-circle size15x', $url,
'', $permissiontoaddaproductline, $parameters);
1475 print
load_fiche_titre($langs->trans(
'Production'), $newcardbutton,
'', 0,
'',
'');
1477 print
'<div class="div-table-responsive-no-min">';
1478 print
'<table id="tablelinestoproduce" class="noborder noshadow nobottom centpercent">';
1480 print
'<tr class="liste_titre">';
1482 print
'<td>'.$langs->trans(
"Product").
'</td>';
1484 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
1487 print
'<td class="right">'.$langs->trans(
"Unit").
'</td>';
1490 if ($permissiontoupdatecost) {
1491 if (empty($bomcostupdated)) {
1492 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"UnitCost"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1494 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"ManufacturingPrice"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1498 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyProducedShort"), $langs->trans(
"QtyAlreadyProduced")).
'</td>';
1501 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1502 print $langs->trans(
"Warehouse");
1507 if (isModEnabled(
'productbatch')) {
1509 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1510 print $langs->trans(
"Batch");
1522 if ($permissiontodelete) {
1528 if ($action ==
'addproduceline') {
1529 print
'<!-- Add line to produce -->'.
"\n";
1530 print
'<tr class="liste_titre">';
1534 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
1537 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
1543 if ($permissiontoupdatecost) {
1547 print
'<td colspan="2">';
1548 print
'<input type="submit" class="button buttongen button-add" name="addproducelinebutton" value="'.$langs->trans(
"Add").
'">';
1549 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdproducelinebutton" value="'.$langs->trans(
"Cancel").
'">';
1552 if (isModEnabled(
'productbatch')) {
1562 if ($permissiontodelete) {
1569 $nblinetoproduce = 0;
1570 foreach (
$object->lines as $line) {
1571 if ($line->role ==
'toproduce') {
1576 $nblinetoproducecursor = 0;
1577 foreach (
$object->lines as $line) {
1578 if ($line->role ==
'toproduce') {
1581 $nblinetoproducecursor++;
1583 $tmpproduct =
new Product($db);
1584 $tmpproduct->fetch($line->fk_product);
1586 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
1587 $alreadyproduced = 0;
1588 foreach ($arrayoflines as $line2) {
1589 $alreadyproduced += $line2[
'qty'];
1592 $suffix =
'_'.$line->id;
1593 print
'<!-- Line to dispatch '.$suffix.
' (toproduce) -->'.
"\n";
1595 print
'<input id="qty_ordered'.$suffix.
'" type="hidden" value="'.$line->qty.
'">';
1596 print
'<input id="qty_dispatched'.$suffix.
'" type="hidden" value="'.$alreadyproduced.
'">';
1600 print
'<td>'.$tmpproduct->getNomUrl(1);
1601 print
'<br><span class="opacitymedium small">'.$tmpproduct->label.
'</span>';
1604 print
'<td class="right">'.$line->qty.
'</td>';
1607 print
'<td class="right">'.measuringUnitString($line->fk_unit,
'',
'', 1).
'</td>';
1610 if ($permissiontoupdatecost) {
1612 $manufacturingcost = 0;
1613 $manufacturingcostsrc =
'';
1615 $manufacturingcost = $bomcostupdated;
1616 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1617 if (empty($manufacturingcost)) {
1618 $manufacturingcost = $bomcost;
1619 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1621 if (empty($manufacturingcost)) {
1622 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1623 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1625 if (empty($manufacturingcost)) {
1626 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1627 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1631 print
'<td class="right nowraponall" title="'.dol_escape_htmltag($manufacturingcostsrc).
'">';
1632 if ($manufacturingcost) {
1633 print
price($manufacturingcost);
1638 print
'<td class="right nowraponall">';
1639 if ($alreadyproduced) {
1641 print
'jQuery(document).ready(function() {
1642 jQuery("#expandtoproduce'.$line->id.
'").click(function() {
1643 console.log("Expand mrp_production line '.$line->id.
'");
1644 jQuery(".expanddetailtoproduce'.$line->id.
'").toggle();';
1645 if ($nblinetoproduce == $nblinetoproducecursor) {
1646 print
'if (jQuery("#tablelinestoproduce").hasClass("nobottom")) { jQuery("#tablelinestoproduce").removeClass("nobottom"); } else { jQuery("#tablelinestoproduce").addClass("nobottom"); }';
1652 if (empty($conf->use_javascript_ajax)) {
1653 print
'<a href="'.$_SERVER[
"PHP_SELF"].
'?collapse='.$collapse.
','.$line->id.
'">';
1655 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce'.$line->id.
'"');
1656 if (empty($conf->use_javascript_ajax)) {
1660 print
' '.$alreadyproduced;
1666 if (isModEnabled(
'productbatch')) {
1676 if ($permissiontodelete) {
1677 if ($line->origin_type ==
'free') {
1678 $href = $_SERVER[
"PHP_SELF"];
1679 $href .=
'?id='.$object->id;
1680 $href .=
'&action=deleteline';
1681 $href .=
'&lineid='.$line->id;
1682 print
'<td class="center">';
1683 print
'<a class="reposition" href="'.$href.
'">';
1684 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
"delete");
1694 foreach ($arrayoflines as $line2) {
1695 print
'<tr class="expanddetailtoproduce'.$line->id.
' hideobject opacitylow">';
1698 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1699 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1709 if ($permissiontoupdatecost) {
1713 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1715 print
'<td class="tdoverflowmax150">';
1716 if ($line2[
'fk_warehouse'] > 0) {
1717 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1719 print $tmpwarehouse->getNomUrl(1);
1724 if (isModEnabled(
'productbatch')) {
1726 if ($line2[
'batch'] !=
'') {
1727 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1728 print $tmpbatch->getNomUrl(1);
1739 if ($permissiontodelete) {
1745 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1746 print
'<!-- Enter line to produce -->'.
"\n";
1748 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1750 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToProduce").
'</span></td>';
1751 $preselected = (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyproduced));
1752 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
1756 print
'<td class="right"><input type="text" class="width50 right" id="qtytoproduce-'.$line->id.
'-'.$i.
'" name="qtytoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1759 print
'<td class="right"></td>';
1762 if ($permissiontoupdatecost) {
1764 $manufacturingcost = 0;
1765 $manufacturingcostsrc =
'';
1767 $manufacturingcost = $bomcostupdated;
1768 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1769 if (empty($manufacturingcost)) {
1770 $manufacturingcost = $bomcost;
1771 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1773 if (empty($manufacturingcost)) {
1774 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1775 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1777 if (empty($manufacturingcost)) {
1778 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1779 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1784 $preselected = (GETPOSTISSET(
'pricetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) : ($manufacturingcost ?
price($manufacturingcost) :
''));
1785 print
'<td class="right"><input type="text" class="width75 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1787 print
'<td><input type="hidden" class="width50 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.($manufacturingcost ? $manufacturingcost :
'').
'"></td>';
1795 $preselected = (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) : (
$object->fk_warehouse > 0 ?
$object->fk_warehouse :
'ifone'));
1796 print $formproduct->selectWarehouses($preselected,
'idwarehousetoproduce-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0,
null,
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1798 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1802 if (isModEnabled(
'productbatch')) {
1804 if ($tmpproduct->status_batch) {
1805 $preselected = (GETPOSTISSET(
'batchtoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i) :
'');
1806 print
'<input type="text" class="width75" name="batchtoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'">';
1810 if ($tmpproduct->status_batch) {
1812 print
'<td align="right" class="split">';
1813 print
img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.$line->id.
', \''.$type.
'\', \
'qtymissing\')"');
1816 print
'<td align="right" class="splitall">';
1817 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1818 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" onClick="addDispatchLine('.$line->id.
', \'batch\', \'alltoproduce\')"');
1844 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline'))) {
1848 <script
type=
"text/javascript" language=
"javascript">
1850 $(document).ready(
function() {
1852 updateselectbatchbywarehouse();
1854 updateselectwarehousebybatch();
1857 function updateselectbatchbywarehouse() {
1858 $(document).on(
'change',
"select[name*='idwarehouse']",
function () {
1859 console.log(
"We change warehouse so we update the list of possible batch number");
1861 var selectwarehouse = $(
this);
1863 var selectbatch_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'batch');
1864 var selectbatch = $(
"datalist[id*='" + selectbatch_name +
"']");
1865 var selectedbatch = selectbatch.val();
1867 var product_element_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'product');
1871 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1873 action:
"updateselectbatchbywarehouse",
1874 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1875 warehouse_id: $(
this).val(),
1876 token:
'<?php echo currentToken(); ?>',
1877 product_id: $(
"input[name='" + product_element_name +
"']").val()
1879 }).done(
function (data) {
1881 selectbatch.empty();
1883 if (typeof data ==
"object") {
1884 console.log(
"data is already type object, no need to parse it");
1886 console.log(
"data is type "+(typeof data));
1887 data = JSON.parse(data);
1890 selectbatch.append($(
'<option>', {
1894 $.each(data,
function (key, value) {
1896 if(selectwarehouse.val() == -1) {
1897 var label =
" (<?php echo $langs->trans('Stock total') ?> : " + value +
")";
1899 var label =
" (<?php echo $langs->trans('Stock') ?> : " + value +
")";
1902 if(key === selectedbatch) {
1903 var option =
'<option value="'+key+
'" selected>'+ label +
'</option>';
1905 var option =
'<option value="'+key+
'">'+ label +
'</option>';
1908 selectbatch.append(option);
1914 function updateselectwarehousebybatch() {
1915 $(document).on(
'change',
'input[name*=batch]',
function(){
1916 console.log(
"We change batch so we update the list of possible warehouses");
1918 var selectbatch = $(
this);
1920 var selectwarehouse_name = selectbatch.attr(
'name').replace(
'batch',
'idwarehouse');
1921 var selectwarehouse = $(
"select[name*='" + selectwarehouse_name +
"']");
1922 var selectedwarehouse = selectwarehouse.val();
1924 if(selectedwarehouse != -1){
1928 var product_element_name = selectbatch.attr(
'name').replace(
'batch',
'product');
1932 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1934 action:
"updateselectwarehousebybatch",
1935 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1936 batch: $(
this).val(),
1937 token:
'<?php echo currentToken(); ?>',
1938 product_id: $(
"input[name='" + product_element_name +
"']").val()
1940 }).done(
function (data) {
1942 if (typeof data ==
"object") {
1943 console.log(
"data is already type object, no need to parse it");
1945 console.log(
"data is type "+(typeof data));
1946 data = JSON.parse(data);
1950 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.
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 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.