27require
'../main.inc.php';
28require_once DOL_DOCUMENT_ROOT.
'/bom/class/bom.class.php';
29require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formcompany.class.php';
30require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formfile.class.php';
31require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formprojet.class.php';
32require_once DOL_DOCUMENT_ROOT.
'/mrp/class/mo.class.php';
33require_once DOL_DOCUMENT_ROOT.
'/mrp/lib/mrp_mo.lib.php';
34require_once DOL_DOCUMENT_ROOT.
'/projet/class/project.class.php';
35require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
36require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
37require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
38require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/productlot.class.php';
39require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
40require_once DOL_DOCUMENT_ROOT.
'/workstation/class/workstation.class.php';
44$langs->loadLangs(array(
"mrp",
"stocks",
"other",
"product",
"productbatch"));
49$action =
GETPOST(
'action',
'aZ09');
50$confirm =
GETPOST(
'confirm',
'alpha');
51$cancel =
GETPOST(
'cancel',
'aZ09');
52$contextpage =
GETPOST(
'contextpage',
'aZ') ?
GETPOST(
'contextpage',
'aZ') :
'mocard';
53$backtopage =
GETPOST(
'backtopage',
'alpha');
54$lineid =
GETPOST(
'lineid',
'int');
55$fk_movement =
GETPOST(
'fk_movement',
'int');
56$fk_default_warehouse =
GETPOST(
'fk_default_warehouse',
'int');
58$collapse =
GETPOST(
'collapse',
'aZ09comma');
63$diroutputmassaction = $conf->mrp->dir_output.
'/temp/massgeneration/'.$user->id;
64$objectline =
new MoLine($db);
66$hookmanager->initHooks(array(
'moproduction',
'globalcard'));
69$extrafields->fetch_name_optionals_label($object->table_element);
71$search_array_options = $extrafields->getOptionalsFromPost($object->table_element,
'',
'search_');
74$search_all =
GETPOST(
"search_all",
'alpha');
76foreach ($object->fields as $key => $val) {
77 if (
GETPOST(
'search_'.$key,
'alpha')) {
78 $search[$key] =
GETPOST(
'search_'.$key,
'alpha');
82if (empty($action) && empty($id) && empty($ref)) {
87include DOL_DOCUMENT_ROOT.
'/core/actions_fetchobject.inc.php';
92$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
93$result =
restrictedArea($user,
'mrp', $object->id,
'mrp_mo',
'',
'fk_soc',
'rowid', $isdraft);
96$permissionnote = $user->rights->mrp->write;
97$permissiondellink = $user->rights->mrp->write;
98$permissiontoadd = $user->rights->mrp->write;
99$permissiontodelete = $user->rights->mrp->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT);
101$permissiontoproduce = $permissiontoadd;
102$permissiontoupdatecost = $user->hasRight(
'bom',
'read');
104$upload_dir = $conf->mrp->multidir_output[isset($object->entity) ? $object->entity : 1];
111$parameters = array();
112$reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
117if (empty($reshook)) {
122 if (empty($backtopage) || ($cancel && empty($id))) {
124 if (empty($id) && (($action !=
'add' && $action !=
'create') || $cancel)) {
125 $backtopage = $backurlforlist;
127 $backtopage = DOL_URL_ROOT.
'/mrp/mo_production.php?id='.($id > 0 ? $id :
'__ID__');
130 $triggermodname =
'MO_MODIFY';
132 if ($action ==
'confirm_cancel' && $confirm ==
'yes' && !empty($permissiontoadd)) {
133 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
134 $result = $object->cancel($user, 0, $also_cancel_consumed_and_produced_lines);
136 header(
"Location: " .
dol_buildpath(
'/mrp/mo_card.php?id=' . $object->id, 1));
142 } elseif ($action ==
'confirm_delete' && $confirm ==
'yes' && !empty($permissiontodelete)) {
143 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
144 $result = $object->delete($user, 0, $also_cancel_consumed_and_produced_lines);
146 header(
"Location: " . $backurlforlist);
155 include DOL_DOCUMENT_ROOT.
'/core/actions_addupdatedelete.inc.php';
158 include DOL_DOCUMENT_ROOT.
'/core/actions_dellink.inc.php';
161 include DOL_DOCUMENT_ROOT.
'/core/actions_printing.inc.php';
164 $triggersendname =
'MO_SENTBYMAIL';
165 $autocopy =
'MAIN_MAIL_AUTOCOPY_MO_TO';
166 $trackid =
'mo'.$object->id;
167 include DOL_DOCUMENT_ROOT.
'/core/actions_sendmails.inc.php';
172 if ($action ==
'set_thirdparty' && $permissiontoadd) {
173 $object->setValueFrom(
'fk_soc',
GETPOST(
'fk_soc',
'int'),
'',
'',
'date',
'', $user, $triggermodname);
175 if ($action ==
'classin' && $permissiontoadd) {
176 $object->setProject(
GETPOST(
'projectid',
'int'));
179 if ($action ==
'confirm_reopen' && $permissiontoadd) {
180 $result = $object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_REOPEN');
183 if (($action ==
'confirm_addconsumeline' &&
GETPOST(
'addconsumelinebutton') && $permissiontoadd)
184 || ($action ==
'confirm_addproduceline' &&
GETPOST(
'addproducelinebutton') && $permissiontoadd)) {
185 $moline =
new MoLine($db);
188 $moline->fk_mo = $object->id;
189 $moline->qty =
GETPOST(
'qtytoadd',
'int');
190 $moline->fk_product =
GETPOST(
'productidtoadd',
'int');
191 if (
GETPOST(
'addconsumelinebutton')) {
192 $moline->role =
'toconsume';
194 $moline->role =
'toproduce';
196 $moline->origin_type =
'free';
197 $moline->position = 0;
200 if (!empty($moline->fk_product)) {
201 $tmpproduct =
new Product($db);
202 $tmpproduct->fetch($moline->fk_product);
204 $moline->fk_default_workstation = $tmpproduct->fk_default_workstation;
207 if ($conf->global->PRODUCT_USE_UNITS) {
208 $moline->fk_unit = $tmpproduct->fk_unit;
212 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
213 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
215 if (is_array($extralabelsline)) {
217 foreach ($extralabelsline as $key => $value) {
218 unset($_POST[
"options_".$key]);
221 if (is_array($array_options) && count($array_options) > 0) {
222 $moline->array_options = $array_options;
225 $resultline = $moline->create($user,
false);
226 if ($resultline <= 0) {
233 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.$object->id);
237 if (in_array($action, array(
'confirm_consumeorproduce',
'confirm_consumeandproduceall')) && $permissiontoproduce) {
240 $labelmovement =
GETPOST(
'inventorylabel',
'alphanohtml');
241 $codemovement =
GETPOST(
'inventorycode',
'alphanohtml');
246 foreach ($object->lines as $line) {
247 if ($line->role ==
'toconsume') {
248 $tmpproduct =
new Product($db);
249 $tmpproduct->fetch($line->fk_product);
252 while (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
255 if ($qtytoprocess != 0) {
257 if (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i)) {
258 if (!(
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0)) {
259 $langs->load(
"errors");
260 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
263 if ($tmpproduct->status_batch && (!
GETPOST(
'batch-'.$line->id.
'-'.$i))) {
264 $langs->load(
"errors");
265 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
271 if (!$error &&
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0) {
273 $id_product_batch = 0;
274 $stockmove->setOrigin($object->element, $object->id);
275 $stockmove->context[
'mrp_role'] =
'toconsume';
277 if ($qtytoprocess >= 0) {
278 $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);
280 $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);
282 if ($idstockmove < 0) {
290 $moline =
new MoLine($db);
291 $moline->fk_mo = $object->id;
292 $moline->position = $pos;
293 $moline->fk_product = $line->fk_product;
294 $moline->fk_warehouse =
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i);
295 $moline->qty = $qtytoprocess;
296 $moline->batch =
GETPOST(
'batch-'.$line->id.
'-'.$i);
297 $moline->role =
'consumed';
298 $moline->fk_mrp_production = $line->id;
299 $moline->fk_stock_movement = $idstockmove == 0 ? null : $idstockmove;
300 $moline->fk_user_creat = $user->id;
302 $resultmoline = $moline->create($user);
303 if ($resultmoline <= 0) {
320 foreach ($object->lines as $line) {
321 if ($line->role ==
'toproduce') {
322 $tmpproduct =
new Product($db);
323 $tmpproduct->fetch($line->fk_product);
326 while (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
328 $pricetoprocess =
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) ?
price2num(
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i)) : 0;
330 if ($qtytoprocess != 0) {
332 if (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i)) {
333 if (!(
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0)) {
334 $langs->load(
"errors");
335 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
338 if (isModEnabled(
'productbatch') && $tmpproduct->status_batch && (!
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i))) {
339 $langs->load(
"errors");
340 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
346 if (!$error &&
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0) {
348 $id_product_batch = 0;
349 $stockmove->origin_type = $object->element;
350 $stockmove->origin_id = $object->id;
351 $stockmove->context[
'mrp_role'] =
'toproduce';
353 $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);
354 if ($idstockmove < 0) {
362 $moline =
new MoLine($db);
363 $moline->fk_mo = $object->id;
364 $moline->position = $pos;
365 $moline->fk_product = $line->fk_product;
366 $moline->fk_warehouse =
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i);
367 $moline->qty = $qtytoprocess;
368 $moline->batch =
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i);
369 $moline->role =
'produced';
370 $moline->fk_mrp_production = $line->id;
371 $moline->fk_stock_movement = $idstockmove;
372 $moline->fk_user_creat = $user->id;
374 $resultmoline = $moline->create($user);
375 if ($resultmoline <= 0) {
390 $consumptioncomplete =
true;
391 $productioncomplete =
true;
393 if (
GETPOST(
'autoclose',
'int')) {
394 foreach ($object->lines as $line) {
395 if ($line->role ==
'toconsume') {
396 $arrayoflines = $object->fetchLinesLinked(
'consumed', $line->id);
397 $alreadyconsumed = 0;
398 foreach ($arrayoflines as $line2) {
399 $alreadyconsumed += $line2[
'qty'];
402 if ($alreadyconsumed < $line->qty) {
403 $consumptioncomplete =
false;
406 if ($line->role ==
'toproduce') {
407 $arrayoflines = $object->fetchLinesLinked(
'produced', $line->id);
408 $alreadyproduced = 0;
409 foreach ($arrayoflines as $line2) {
410 $alreadyproduced += $line2[
'qty'];
413 if ($alreadyproduced < $line->qty) {
414 $productioncomplete =
false;
419 $consumptioncomplete =
false;
420 $productioncomplete =
false;
424 dol_syslog(
"consumptioncomplete = ".$consumptioncomplete.
" productioncomplete = ".$productioncomplete);
426 if ($consumptioncomplete && $productioncomplete) {
427 $result = $object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
429 $result = $object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_MO_PRODUCED');
438 $action = str_replace(
'confirm_',
'', $action);
444 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.$object->id);
450 if ($action ==
'confirm_produced' && $confirm ==
'yes' && $permissiontoadd) {
451 $result = $object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
455 $outputlangs = $langs;
458 $newlang =
GETPOST(
'lang_id',
'aZ09');
461 $newlang = $object->thirdparty->default_lang;
463 if (!empty($newlang)) {
465 $outputlangs->setDefaultLang($newlang);
467 $model = $object->model_pdf;
468 $ret = $object->fetch($id);
470 $object->generateDocument($model, $outputlangs, 0, 0, 0);
477 if ($action ==
'confirm_editline' && $permissiontoadd) {
478 $moline =
new MoLine($db);
479 $res = $moline->fetch(
GETPOST(
'lineid',
'int'));
481 $extrafields->fetch_name_optionals_label($moline->element);
482 foreach ($extrafields->attributes[$moline->table_element][
'label'] as $key => $label) {
483 $value =
GETPOST(
'options_'.$key,
'alphanohtml');
484 $moline->array_options[
"options_".$key] = $value;
486 $moline->qty =
GETPOST(
'qty_lineProduce',
'int');
487 $res = $moline->update($user);
490 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.$object->id);
493 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.$object->id);
505$form =
new Form($db);
512$help_url =
'EN:Module_Manufacturing_Orders|FR:Module_Ordres_de_Fabrication|DE:Modul_Fertigungsauftrag';
513$morejs = array(
'/mrp/js/lib_dispatch.js.php');
514llxHeader(
'', $langs->trans(
'Mo'), $help_url,
'', 0, 0, $morejs);
516$newToken = newToken();
519if ($object->id > 0 && (empty($action) || ($action !=
'edit' && $action !=
'create'))) {
520 $res = $object->fetch_thirdparty();
521 $res = $object->fetch_optionals();
523 if (
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') && $object->fk_warehouse > 0) {
524 $tmpwarehouse->fetch($object->fk_warehouse);
525 $fk_default_warehouse = $object->fk_warehouse;
530 print
dol_get_fiche_head($head,
'production', $langs->trans(
"ManufacturingOrder"), -1, $object->picto);
535 if ($action ==
'delete') {
536 $formquestion = array(
538 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
539 'name' =>
'alsoCancelConsumedAndProducedLines',
540 'type' =>
'checkbox',
544 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.$object->id, $langs->trans(
'DeleteMo'), $langs->trans(
'ConfirmDeleteMo'),
'confirm_delete', $formquestion, 0, 1);
547 if ($action ==
'deleteline') {
548 $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);
551 if ($action ==
'clone') {
553 $formquestion = array();
554 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.$object->id, $langs->trans(
'ToClone'), $langs->trans(
'ConfirmCloneMo', $object->ref),
'confirm_clone', $formquestion,
'yes', 1);
558 if ($action ==
'validate') {
560 $ref = substr($object->ref, 1, 4);
561 if ($ref ==
'PROV') {
562 $object->fetch_product();
563 $numref = $object->getNextNumRef($object->product);
565 $numref = $object->ref;
568 $text = $langs->trans(
'ConfirmValidateMo', $numref);
577 $formquestion = array();
578 if (isModEnabled(
'mrp')) {
580 require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
583 if ($conf->browser->name ==
'ie') {
586 $formquestion = array(
593 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.$object->id, $langs->trans(
'Validate'), $text,
'confirm_validate', $formquestion, 0, 1, 220);
597 if ($action ==
'cancel') {
598 $formquestion = array(
600 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
601 'name' =>
'alsoCancelConsumedAndProducedLines',
602 'type' =>
'checkbox',
603 'value' => !
getDolGlobalString(
'MO_ALSO_CANCEL_CONSUMED_AND_PRODUCED_LINES_BY_DEFAULT') ? 0 : 1
606 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"] .
'?id=' . $object->id, $langs->trans(
'CancelMo'), $langs->trans(
'ConfirmCancelMo'),
'confirm_cancel', $formquestion, 0, 1);
610 $parameters = array(
'formConfirm' => $formconfirm,
'lineid' => $lineid);
611 $reshook = $hookmanager->executeHooks(
'formConfirm', $parameters, $object, $action);
612 if (empty($reshook)) {
613 $formconfirm .= $hookmanager->resPrint;
614 } elseif ($reshook > 0) {
615 $formconfirm = $hookmanager->resPrint;
624 $linkback =
'<a href="'.DOL_URL_ROOT.
'/mrp/mo_list.php?restore_lastsearch_values=1'.(!empty($socid) ?
'&socid='.$socid :
'').
'">'.$langs->trans(
"BackToList").
'</a>';
626 $morehtmlref =
'<div class="refidno">';
635 if (is_object($object->thirdparty)) {
636 $morehtmlref .= $object->thirdparty->getNomUrl(1,
'customer');
638 $morehtmlref .=
' (<a href="'.DOL_URL_ROOT.
'/commande/list.php?socid='.$object->thirdparty->id.
'&search_societe='.urlencode($object->thirdparty->name).
'">'.$langs->trans(
"OtherOrders").
'</a>)';
643 if (isModEnabled(
'project')) {
644 $langs->load(
"projects");
645 if (is_object($object->thirdparty)) {
646 $morehtmlref .=
'<br>';
648 if ($permissiontoadd) {
649 $morehtmlref .=
img_picto($langs->trans(
"Project"),
'project',
'class="pictofixedwidth"');
650 if ($action !=
'classify') {
651 $morehtmlref .=
'<a class="editfielda" href="'.$_SERVER[
'PHP_SELF'].
'?action=classify&token='.newToken().
'&id='.$object->id.
'">'.
img_edit($langs->transnoentitiesnoconv(
'SetProject')).
'</a> ';
653 $morehtmlref .= $form->form_project($_SERVER[
'PHP_SELF'].
'?id='.$object->id, $object->socid, $object->fk_project, ($action ==
'classify' ?
'projectid' :
'none'), 0, 0, 0, 1,
'',
'maxwidth300');
655 if (!empty($object->fk_project)) {
657 $proj->fetch($object->fk_project);
658 $morehtmlref .= $proj->getNomUrl(1);
660 $morehtmlref .=
'<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).
'</span>';
665 $morehtmlref .=
'</div>';
668 dol_banner_tab($object,
'ref', $linkback, 1,
'ref',
'ref', $morehtmlref);
671 print
'<div class="fichecenter">';
672 print
'<div class="fichehalfleft">';
673 print
'<div class="underbanner clearboth"></div>';
674 print
'<table class="border centpercent tableforfield">'.
"\n";
677 $keyforbreak =
'fk_warehouse';
678 unset($object->fields[
'fk_project']);
679 unset($object->fields[
'fk_soc']);
680 include DOL_DOCUMENT_ROOT.
'/core/tpl/commonfields_view.tpl.php';
683 include DOL_DOCUMENT_ROOT.
'/core/tpl/extrafields_view.tpl.php';
689 print
'<div class="clearboth"></div>';
694 if (!in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
695 print
'<div class="tabsAction">';
697 $parameters = array();
699 $reshook = $hookmanager->executeHooks(
'addMoreActionsButtons', $parameters, $object, $action);
700 if (empty($reshook)) {
702 if ($object->status == $object::STATUS_DRAFT) {
703 if ($permissiontoadd) {
704 if (empty($object->table_element_line) || (is_array($object->lines) && count($object->lines) > 0)) {
705 print
'<a class="butAction" href="'.$_SERVER[
'PHP_SELF'].
'?id='.$object->id.
'&action=validate&token='.$newToken.
'">'.$langs->trans(
"Validate").
'</a>';
707 $langs->load(
"errors");
708 print
'<a class="butActionRefused" href="" title="'.$langs->trans(
"ErrorAddAtLeastOneLineFirst").
'">'.$langs->trans(
"Validate").
'</a>';
714 if ($object->status == Mo::STATUS_VALIDATED || $object->status == Mo::STATUS_INPROGRESS) {
715 if ($permissiontoproduce) {
716 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$object->id.
'&action=consumeorproduce&token='.$newToken.
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
718 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
720 } elseif ($object->status == Mo::STATUS_DRAFT) {
721 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
725 if ($object->status == Mo::STATUS_VALIDATED || $object->status == Mo::STATUS_INPROGRESS) {
726 if ($permissiontoproduce) {
727 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$object->id.
'&action=consumeandproduceall&token='.$newToken.
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
729 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
731 } elseif ($object->status == Mo::STATUS_DRAFT) {
732 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
736 if ($permissiontoadd) {
737 if ($object->status == $object::STATUS_VALIDATED || $object->status == $object::STATUS_INPROGRESS) {
738 $arrayproduced = $object->fetchLinesLinked(
'produced', 0);
740 foreach ($arrayproduced as $lineproduced) {
741 $nbProduced += $lineproduced[
'qty'];
743 if ($nbProduced > 0) {
744 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$object->id.
'&action=confirm_produced&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
746 print
'<a class="butActionRefused" href="#" title="'.$langs->trans(
"GoOnTabProductionToProduceFirst", $langs->transnoentitiesnoconv(
"Production")).
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
749 print
'<a class="butActionDelete" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$object->id.
'&action=cancel&token='.$newToken.
'">'.$langs->trans(
"Cancel").
'</a>'.
"\n";
752 if ($object->status == $object::STATUS_CANCELED) {
753 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$object->id.
'&action=confirm_reopen&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"ReOpen").
'</a>'.
"\n";
756 if ($object->status == $object::STATUS_PRODUCED) {
757 if ($permissiontoproduce) {
758 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$object->id.
'&action=confirm_reopen&token='.$newToken.
'">'.$langs->trans(
'ReOpen').
'</a>';
760 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ReOpen').
'</a>';
769 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline',
'addproduceline',
'editline'))) {
770 print
'<form method="POST" action="'.$_SERVER[
"PHP_SELF"].
'">';
771 print
'<input type="hidden" name="token" value="'.newToken().
'">';
772 print
'<input type="hidden" name="action" value="confirm_'.$action.
'">';
773 print
'<input type="hidden" name="backtopage" value="'.$backtopage.
'">';
774 print
'<input type="hidden" name="id" value="'.$id.
'">';
777 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
778 $defaultstockmovementlabel =
GETPOST(
'inventorylabel',
'alphanohtml') ?
GETPOST(
'inventorylabel',
'alphanohtml') : $langs->trans(
"ProductionForRef", $object->
ref);
781 print
'<div class="center'.(in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) ?
' formconsumeproduce' :
'').
'">';
782 print
'<div class="opacitymedium hideonsmartphone paddingbottom">'.$langs->trans(
"ConfirmProductionDesc", $langs->transnoentitiesnoconv(
"Confirm")).
'<br></div>';
783 print
'<span class="fieldrequired">'.$langs->trans(
"InventoryCode").
':</span> <input type="text" class="minwidth150 maxwidth200" name="inventorycode" value="'.$defaultstockmovementcode.
'"> ';
784 print
'<span class="clearbothonsmartphone"></span>';
785 print $langs->trans(
"MovementLabel").
': <input type="text" class="minwidth300" name="inventorylabel" value="'.$defaultstockmovementlabel.
'"><br><br>';
786 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>';
787 print
'<input type="submit" class="button" value="'.$langs->trans(
"Confirm").
'" name="confirm">';
789 print
'<input class="button button-cancel" type="submit" value="'.$langs->trans(
"Cancel").
'" name="cancel">';
803 if (!empty($object->table_element_line)) {
805 $object->fetchLines();
808 if ($object->fk_bom > 0) {
810 $res = $bom->fetch($object->fk_bom);
812 $bom->calculateCosts();
813 $bomcost = $bom->unit_cost;
819 print
'<div class="fichecenter">';
820 print
'<div class="fichehalfleft">';
821 print
'<div class="clearboth"></div>';
823 $url = $_SERVER[
"PHP_SELF"].
'?id='.$object->id.
'&action=addconsumeline&token='.newToken();
824 $permissiontoaddaconsumeline = $object->status != $object::STATUS_PRODUCED && $object->status != $object::STATUS_CANCELED;
825 $parameters = array(
'morecss'=>
'reposition');
828 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
829 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewConsumeLines'),
'',
'fa fa-plus-circle size15x', $url,
'', $permissiontoaddaconsumeline, $parameters);
832 print
load_fiche_titre($langs->trans(
'Consumption'), $newcardbutton,
'', 0,
'',
'',
'');
834 print
'<div class="div-table-responsive-no-min">';
835 print
'<table class="noborder noshadow centpercent nobottom">';
837 print
'<tr class="liste_titre">';
839 print
'<td>'.$langs->trans(
"Product").
'</td>';
841 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
843 if ($conf->global->PRODUCT_USE_UNITS) {
844 print
'<td class="right">' . $langs->trans(
"Unit") .
'</td>';
848 print
'<td class="right">'.$langs->trans(
"UnitCost").
'</td>';
851 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyConsumedShort"), $langs->trans(
"QtyAlreadyConsumed")).
'</td>';
854 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
855 print $langs->trans(
"Warehouse");
856 if (isModEnabled(
'workstation')) {
857 print
' '.$langs->trans(
"or").
' '.$langs->trans(
"Workstation");
860 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
861 $listwarehouses = $tmpwarehouse->list_array(1);
862 if (count($listwarehouses) > 1) {
863 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, $langs->trans(
"ForceTo"), 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
864 } elseif (count($listwarehouses) == 1) {
865 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
871 if (isModEnabled(
'stock')) {
873 print
'<td align="right">';
874 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
875 print $langs->trans(
"Stock");
880 if (isModEnabled(
'productbatch')) {
882 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
883 print $langs->trans(
"Batch");
888 if ($permissiontodelete) {
899 if ($object->status == Mo::STATUS_DRAFT) {
905 if ($action ==
'addconsumeline') {
906 print
'<!-- Add line to consume -->'.
"\n";
907 print
'<tr class="liste_titre">';
910 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
913 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
914 if ($conf->global->PRODUCT_USE_UNITS) {
922 print
'<td colspan="2">';
923 print
'<input type="submit" class="button buttongen button-add" name="addconsumelinebutton" value="'.$langs->trans(
"Add").
'">';
924 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdconsumelinebutton" value="'.$langs->trans(
"Cancel").
'">';
926 if (isModEnabled(
'stock')) {
930 if (isModEnabled(
'productbatch')) {
934 if ($permissiontodelete) {
942 if ($object->status == Mo::STATUS_DRAFT) {
948 if (is_object($objectline)) {
949 $extrafields->fetch_name_optionals_label($object->table_element_line);
950 $temps = $objectline->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
951 if (!empty($temps)) {
952 print
'<tr class="liste_titre"><td style="padding-top: 20px" colspan="9" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
963 if (!empty($object->lines)) {
964 $nblinetoconsume = 0;
965 foreach ($object->lines as $line) {
966 if ($line->role ==
'toconsume') {
971 $nblinetoconsumecursor = 0;
972 foreach ($object->lines as $line) {
973 if ($line->role ==
'toconsume') {
974 $nblinetoconsumecursor++;
976 $tmpproduct =
new Product($db);
977 $tmpproduct->fetch($line->fk_product);
978 $linecost =
price2num($tmpproduct->pmp,
'MT');
980 if ($object->qty > 0) {
982 $costprice =
price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp);
983 if (empty($costprice)) {
984 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
986 if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) {
987 $costprice = $productFournisseur->fourn_unitprice;
992 $linecost =
price2num(($line->qty * $costprice) / $object->qty,
'MT');
993 $bomcostupdated +=
price2num(($line->qty * $costprice) / $object->qty,
'MU');
996 $bomcostupdated =
price2num($bomcostupdated,
'MU');
997 $arrayoflines = $object->fetchLinesLinked(
'consumed', $line->id);
998 $alreadyconsumed = 0;
999 foreach ($arrayoflines as $line2) {
1000 $alreadyconsumed += $line2[
'qty'];
1003 if ($action ==
'editline' && $lineid == $line->id) {
1004 $linecost =
price2num($tmpproduct->pmp,
'MT');
1006 $arrayoflines = $object->fetchLinesLinked(
'consumed', $line->id);
1007 $alreadyconsumed = 0;
1008 if (is_array($arrayoflines) && !empty($arrayoflines)) {
1009 foreach ($arrayoflines as $line2) {
1010 $alreadyconsumed += $line2[
'qty'];
1013 $suffix =
'_' . $line->id;
1014 print
'<!-- Line to dispatch ' . $suffix .
' -->' .
"\n";
1016 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1018 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1020 print
'<input name="lineid" type="hidden" value="' . $line->id .
'">';
1023 print
'<td>' . $tmpproduct->getNomUrl(1);
1024 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</span>';
1028 print
'<td class="right nowraponall">';
1029 print
'<input class="width40" name="qty_lineProduce" value="'. $line->qty.
'">';
1032 if ($conf->global->PRODUCT_USE_UNITS) {
1033 print
'<td class="right nowraponall">';
1038 print
'<td class="right">';
1039 print
' ' .
price2num($alreadyconsumed,
'MS');
1042 print
'<td class="right">';
1045 print
'<td class="nowraponall right">';
1046 if ($tmpproduct->isStockManaged()) {
1047 if ($tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1048 print
img_warning($langs->trans(
'StockTooLow')).
' ';
1050 print
'<span class="left">'. $tmpproduct->stock_reel .
' </span>';
1061 print
'<td colspan="2">';
1062 print
'<input type="submit" class="button buttongen button-add small nominwidth" name="save" value="' . $langs->trans(
"Save") .
'">';
1063 print
'<input type="submit" class="button buttongen button-cancel small nominwidth" name="cancel" value="' . $langs->trans(
"Cancel") .
'">';
1067 if ($permissiontodelete) {
1074 if (!empty($extrafields)) {
1075 $line->fetch_optionals();
1076 $temps = $line->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
1077 if (!empty($temps)) {
1078 print
'<td colspan="10"><div style="padding-top: 20px" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
1080 print
'</div></td>';
1084 $suffix =
'_' . $line->id;
1085 print
'<!-- Line to dispatch ' . $suffix .
' -->' .
"\n";
1087 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1088 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1090 print
'<tr data-line-id="' . $line->id .
'">';
1092 print
'<td>' . $tmpproduct->getNomUrl(1);
1093 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</div>';
1096 print
'<td class="right nowraponall">';
1099 if ($line->qty_frozen) {
1100 $help = ($help ?
'<br>' :
'') .
'<strong>' . $langs->trans(
"QuantityFrozen") .
'</strong>: ' .
yn(1) .
' (' . $langs->trans(
"QuantityConsumedInvariable") .
')';
1101 print $form->textwithpicto(
'', $help, -1,
'lock') .
' ';
1103 if ($line->disable_stock_change) {
1104 $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")) .
')';
1105 print $form->textwithpicto(
'', $help, -1,
'help') .
' ';
1110 if ($conf->global->PRODUCT_USE_UNITS) {
1111 print
'<td class="right nowraponall">';
1116 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1117 print
'<td class="right nowraponall">';
1118 print
price($linecost);
1122 print
'<td class="right">';
1123 if ($alreadyconsumed) {
1125 print
'jQuery(document).ready(function() {
1126 jQuery("#expandtoproduce' . $line->id .
'").click(function() {
1127 console.log("Expand mrp_production line ' . $line->id .
'");
1128 jQuery(".expanddetail' . $line->id .
'").toggle();';
1129 if ($nblinetoconsume == $nblinetoconsumecursor) {
1130 print
'if (jQuery("#tablelines").hasClass("nobottom")) { jQuery("#tablelines").removeClass("nobottom"); } else { jQuery("#tablelines").addClass("nobottom"); }';
1136 if (empty($conf->use_javascript_ajax)) {
1137 print
'<a href="' . $_SERVER[
"PHP_SELF"] .
'?collapse=' . $collapse .
',' . $line->id .
'">';
1139 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce' . $line->id .
'"');
1140 if (empty($conf->use_javascript_ajax)) {
1144 if ($nblinetoconsume == $nblinetoconsumecursor) {
1145 print
'<script>jQuery("#tablelines").removeClass("nobottom");</script>';
1148 print
' ' .
price2num($alreadyconsumed,
'MS');
1152 if (
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') && $tmpwarehouse->id > 0) {
1153 print
img_picto(
'', $tmpwarehouse->picto) .
" " . $tmpwarehouse->label;
1155 if (isModEnabled(
'workstation') && $line->fk_default_workstation > 0) {
1157 $tmpworkstation->fetch($line->fk_default_workstation);
1158 print $tmpworkstation->getNomUrl(1);
1162 if (isModEnabled(
'stock')) {
1163 print
'<td class="nowraponall right">';
1165 if (!$line->disable_stock_change && $tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1166 print
img_warning($langs->trans(
'StockTooLow')) .
' ';
1168 if (!
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') || empty($tmpwarehouse->id)) {
1169 print
price2num($tmpproduct->stock_reel,
'MS');
1172 $tmpproduct->load_stock();
1173 $wh_stock = $tmpproduct->stock_warehouse[$tmpwarehouse->id];
1174 if (!empty($wh_stock)) {
1184 if (isModEnabled(
'productbatch')) {
1195 if ($object->status == Mo::STATUS_DRAFT) {
1196 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int) $object->id) .
'&action=editline&token=' . newToken() .
'&lineid=' . ((int) $line->id);
1197 print
'<td class="center">';
1198 print
'<a class="reposition" href="' . $href .
'">';
1199 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1205 if ($permissiontodelete) {
1206 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int) $object->id) .
'&action=deleteline&token=' . newToken() .
'&lineid=' . ((int) $line->id);
1207 print
'<td class="center">';
1208 print
'<a class="reposition" href="' . $href .
'">';
1209 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1216 if (!empty($extrafields)) {
1217 $line->fetch_optionals();
1218 $temps = $line->showOptionals($extrafields,
'view', array(),
'',
'', 1,
'line');
1219 if (!empty($temps)) {
1220 print
'<td colspan="10"><div id="extrafield_lines_area_'.$line->id.
'" name="extrafield_lines_area_'.$line->id.
'">';
1222 print
'</div></td>';
1227 foreach ($arrayoflines as $line2) {
1228 print
'<tr class="expanddetail'.$line->id.
' hideobject opacitylow">';
1232 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1233 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1241 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1244 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1249 print
'<td class="tdoverflowmax150">';
1250 if ($line2[
'fk_warehouse'] > 0) {
1251 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1253 print $tmpwarehouse->getNomUrl(1);
1259 if (isModEnabled(
'stock')) {
1264 if (isModEnabled(
'productbatch')) {
1266 if ($line2[
'batch'] !=
'') {
1267 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1268 print $tmpbatch->getNomUrl(1);
1280 if ($object->status == Mo::STATUS_DRAFT) {
1281 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int) $object->id) .
'&action=editline&token=' . newToken() .
'&lineid=' . ((int) $line2[
'rowid']);
1282 print
'<td class="center">';
1283 print
'<a class="reposition" href="' . $href .
'">';
1284 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1290 if ($permissiontodelete) {
1291 $href = $_SERVER[
"PHP_SELF"].
'?id='.((int) $object->id).
'&action=deleteline&token='.newToken().
'&lineid='.((int) $line2[
'rowid']).
'&fk_movement='.((int) $line2[
'fk_stock_movement']);
1292 print
'<td class="center">';
1293 print
'<a class="reposition" href="'.$href.
'">';
1294 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1302 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1304 print
'<!-- Enter line to consume -->'.
"\n";
1306 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1308 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToConsume").
'</span></td>';
1309 $preselected = (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i) ?
GETPOST(
'qty-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyconsumed));
1310 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
1315 if (
getDolGlobalString(
'MRP_NEVER_CONSUME_MORE_THAN_EXPECTED') && ($line->qty - $alreadyconsumed) <= 0) {
1316 $disable =
'disabled';
1320 print
'<input type="hidden" name="product-'.$line->id.
'-'.$i.
'" value="'.$line->fk_product.
'">';
1323 print
'<td class="right"><input type="text" class="width50 right" id="qtytoconsume-' . $line->id .
'-' . $i .
'" name="qty-' . $line->id .
'-' . $i .
'" value="' . $preselected .
'" ' . $disable .
'></td>';
1326 if ($conf->global->PRODUCT_USE_UNITS) {
1331 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1341 if (empty($line->disable_stock_change)) {
1342 $preselected = (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) : ($tmpproduct->fk_default_warehouse > 0 ? $tmpproduct->fk_default_warehouse :
'ifone'));
1343 print $formproduct->selectWarehouses($preselected,
'idwarehouse-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0,
null,
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1345 print
'<span class="opacitymedium">'.$langs->trans(
"DisableStockChange").
'</span>';
1348 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1353 if (isModEnabled(
'stock')) {
1358 if (isModEnabled(
'productbatch')) {
1359 print
'<td class="nowraponall">';
1360 if ($tmpproduct->status_batch) {
1361 $preselected = (GETPOSTISSET(
'batch-'.$line->id.
'-'.$i) ?
GETPOST(
'batch-'.$line->id.
'-'.$i) :
'');
1362 print
'<input type="text" class="width75" name="batch-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'" list="batch-'.$line->id.
'-'.$i.
'">';
1363 print $formproduct->selectLotDataList(
'batch-'.$line->id.
'-'.$i, 0, $line->fk_product,
'',
'');
1370 print
'<td align="right" class="split">';
1371 print
' '.img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.((int) $line->id).
', \''.
dol_escape_js($type).
'\', \
'qtymissingconsume\')"');
1375 print
'<td align="right" class="splitall">';
1376 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1377 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" data-max-qty="1" onClick="addDispatchLine('.$line->id.
', \'batch\', \'allmissingconsume\')"');
1382 if ($object->status == Mo::STATUS_DRAFT) {
1387 if ($permissiontodelete) {
1401 print
'<script type="text/javascript">
1402 $(document).ready(function () {
1403 $("select[name=fk_default_warehouse]").change(function() {
1404 var fk_default_warehouse = $("option:selected", this).val();
1405 $("select[name^=idwarehouse-]").val(fk_default_warehouse).change();
1410 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) &&
1412 print
'<script>$(document).ready(function () {
1413 $("#fk_default_warehouse").change();
1421 print
'<div class="fichehalfright">';
1422 print
'<div class="clearboth"></div>';
1424 $nblinetoproduce = 0;
1425 foreach ($object->lines as $line) {
1426 if ($line->role ==
'toproduce') {
1431 $newcardbutton =
'';
1432 $url = $_SERVER[
"PHP_SELF"].
'?id='.$object->id.
'&action=addproduceline&token='.newToken();
1433 $permissiontoaddaproductline = $object->status != $object::STATUS_PRODUCED && $object->status != $object::STATUS_CANCELED;
1434 $parameters = array(
'morecss'=>
'reposition');
1435 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
1436 if ($nblinetoproduce == 0 || $object->mrptype == 1) {
1437 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewProduceLines'),
'',
'fa fa-plus-circle size15x', $url,
'', $permissiontoaddaproductline, $parameters);
1441 print
load_fiche_titre($langs->trans(
'Production'), $newcardbutton,
'', 0,
'',
'');
1443 print
'<div class="div-table-responsive-no-min">';
1444 print
'<table id="tablelinestoproduce" class="noborder noshadow nobottom centpercent">';
1446 print
'<tr class="liste_titre">';
1448 print
'<td>'.$langs->trans(
"Product").
'</td>';
1450 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
1452 if ($conf->global->PRODUCT_USE_UNITS) {
1453 print
'<td class="right">'.$langs->trans(
"Unit").
'</td>';
1456 if ($permissiontoupdatecost) {
1457 if (empty($bomcostupdated)) {
1458 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"UnitCost"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1460 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"ManufacturingPrice"), $langs->trans(
"AmountUsedToUpdateWAP")).
'</td>';
1464 print
'<td class="right">'.$form->textwithpicto($langs->trans(
"QtyAlreadyProducedShort"), $langs->trans(
"QtyAlreadyProduced")).
'</td>';
1467 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1468 print $langs->trans(
"Warehouse");
1473 if (isModEnabled(
'productbatch')) {
1475 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1476 print $langs->trans(
"Batch");
1488 if ($permissiontodelete) {
1494 if ($action ==
'addproduceline') {
1495 print
'<!-- Add line to produce -->'.
"\n";
1496 print
'<tr class="liste_titre">';
1500 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
1503 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
1505 if ($conf->global->PRODUCT_USE_UNITS) {
1509 if ($permissiontoupdatecost) {
1513 print
'<td colspan="2">';
1514 print
'<input type="submit" class="button buttongen button-add" name="addproducelinebutton" value="'.$langs->trans(
"Add").
'">';
1515 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdproducelinebutton" value="'.$langs->trans(
"Cancel").
'">';
1518 if (isModEnabled(
'productbatch')) {
1528 if ($permissiontodelete) {
1534 if (!empty($object->lines)) {
1535 $nblinetoproduce = 0;
1536 foreach ($object->lines as $line) {
1537 if ($line->role ==
'toproduce') {
1542 $nblinetoproducecursor = 0;
1543 foreach ($object->lines as $line) {
1544 if ($line->role ==
'toproduce') {
1547 $nblinetoproducecursor++;
1549 $tmpproduct =
new Product($db);
1550 $tmpproduct->fetch($line->fk_product);
1552 $arrayoflines = $object->fetchLinesLinked(
'produced', $line->id);
1553 $alreadyproduced = 0;
1554 foreach ($arrayoflines as $line2) {
1555 $alreadyproduced += $line2[
'qty'];
1558 $suffix =
'_'.$line->id;
1559 print
'<!-- Line to dispatch '.$suffix.
' -->'.
"\n";
1561 print
'<input id="qty_ordered'.$suffix.
'" type="hidden" value="'.$line->qty.
'">';
1562 print
'<input id="qty_dispatched'.$suffix.
'" type="hidden" value="'.$alreadyproduced.
'">';
1566 print
'<td>'.$tmpproduct->getNomUrl(1);
1567 print
'<br><span class="opacitymedium small">'.$tmpproduct->label.
'</span>';
1570 print
'<td class="right">'.$line->qty.
'</td>';
1572 if ($conf->global->PRODUCT_USE_UNITS) {
1573 print
'<td class="right">'.measuringUnitString($line->fk_unit,
'',
'', 1).
'</td>';
1576 if ($permissiontoupdatecost) {
1578 $manufacturingcost = 0;
1579 $manufacturingcostsrc =
'';
1580 if ($object->mrptype == 0) {
1581 $manufacturingcost = $bomcostupdated;
1582 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1583 if (empty($manufacturingcost)) {
1584 $manufacturingcost = $bomcost;
1585 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1587 if (empty($manufacturingcost)) {
1588 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1589 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1591 if (empty($manufacturingcost)) {
1592 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1593 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1597 print
'<td class="right nowraponall" title="'.dol_escape_htmltag($manufacturingcostsrc).
'">';
1598 if ($manufacturingcost) {
1599 print
price($manufacturingcost);
1604 print
'<td class="right nowraponall">';
1605 if ($alreadyproduced) {
1607 print
'jQuery(document).ready(function() {
1608 jQuery("#expandtoproduce'.$line->id.
'").click(function() {
1609 console.log("Expand mrp_production line '.$line->id.
'");
1610 jQuery(".expanddetailtoproduce'.$line->id.
'").toggle();';
1611 if ($nblinetoproduce == $nblinetoproducecursor) {
1612 print
'if (jQuery("#tablelinestoproduce").hasClass("nobottom")) { jQuery("#tablelinestoproduce").removeClass("nobottom"); } else { jQuery("#tablelinestoproduce").addClass("nobottom"); }';
1618 if (empty($conf->use_javascript_ajax)) {
1619 print
'<a href="'.$_SERVER[
"PHP_SELF"].
'?collapse='.$collapse.
','.$line->id.
'">';
1621 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce'.$line->id.
'"');
1622 if (empty($conf->use_javascript_ajax)) {
1626 print
' '.$alreadyproduced;
1632 if (isModEnabled(
'productbatch')) {
1642 if ($permissiontodelete) {
1643 if ($line->origin_type ==
'free') {
1644 $href = $_SERVER[
"PHP_SELF"];
1645 $href .=
'?id='.$object->id;
1646 $href .=
'&action=deleteline';
1647 $href .=
'&lineid='.$line->id;
1648 print
'<td class="center">';
1649 print
'<a class="reposition" href="'.$href.
'">';
1650 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
"delete");
1660 foreach ($arrayoflines as $line2) {
1661 print
'<tr class="expanddetailtoproduce'.$line->id.
' hideobject opacitylow">';
1664 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1665 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1671 if ($conf->global->PRODUCT_USE_UNITS) {
1675 if ($permissiontoupdatecost) {
1679 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1681 print
'<td class="tdoverflowmax150">';
1682 if ($line2[
'fk_warehouse'] > 0) {
1683 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1685 print $tmpwarehouse->getNomUrl(1);
1690 if (isModEnabled(
'productbatch')) {
1692 if ($line2[
'batch'] !=
'') {
1693 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1694 print $tmpbatch->getNomUrl(1);
1705 if ($permissiontodelete) {
1711 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1712 print
'<!-- Enter line to produce -->'.
"\n";
1714 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1716 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToProduce").
'</span></td>';
1717 $preselected = (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyproduced));
1718 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
1722 print
'<td class="right"><input type="text" class="width50 right" id="qtytoproduce-'.$line->id.
'-'.$i.
'" name="qtytoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1724 if ($conf->global->PRODUCT_USE_UNITS) {
1725 print
'<td class="right"></td>';
1728 if ($permissiontoupdatecost) {
1730 $manufacturingcost = 0;
1731 $manufacturingcostsrc =
'';
1732 if ($object->mrptype == 0) {
1733 $manufacturingcost = $bomcostupdated;
1734 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1735 if (empty($manufacturingcost)) {
1736 $manufacturingcost = $bomcost;
1737 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1739 if (empty($manufacturingcost)) {
1740 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1741 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1743 if (empty($manufacturingcost)) {
1744 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1745 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1750 $preselected = (GETPOSTISSET(
'pricetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) : ($manufacturingcost ?
price($manufacturingcost) :
''));
1751 print
'<td class="right"><input type="text" class="width75 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1753 print
'<td><input type="hidden" class="width50 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.($manufacturingcost ? $manufacturingcost :
'').
'"></td>';
1761 $preselected = (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) : ($object->fk_warehouse > 0 ? $object->fk_warehouse :
'ifone'));
1762 print $formproduct->selectWarehouses($preselected,
'idwarehousetoproduce-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0,
null,
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1764 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1768 if (isModEnabled(
'productbatch')) {
1770 if ($tmpproduct->status_batch) {
1771 $preselected = (GETPOSTISSET(
'batchtoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i) :
'');
1772 print
'<input type="text" class="width75" name="batchtoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'">';
1776 if ($tmpproduct->status_batch) {
1778 print
'<td align="right" class="split">';
1779 print
img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.$line->id.
', \''.$type.
'\', \
'qtymissing\')"');
1782 print
'<td align="right" class="splitall">';
1783 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1784 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" onClick="addDispatchLine('.$line->id.
', \'batch\', \'alltoproduce\')"');
1810 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline'))) {
1814 <script
type=
"text/javascript" language=
"javascript">
1816 $(document).ready(
function() {
1818 updateselectbatchbywarehouse();
1820 updateselectwarehousebybatch();
1823 function updateselectbatchbywarehouse() {
1824 $(document).on(
'change',
"select[name*='idwarehouse']",
function () {
1825 console.log(
"We change warehouse so we update the list of possible batch number");
1827 var selectwarehouse = $(
this);
1829 var selectbatch_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'batch');
1830 var selectbatch = $(
"datalist[id*='" + selectbatch_name +
"']");
1831 var selectedbatch = selectbatch.val();
1833 var product_element_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'product');
1837 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1839 action:
"updateselectbatchbywarehouse",
1840 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1841 warehouse_id: $(
this).val(),
1842 token:
'<?php echo currentToken(); ?>',
1843 product_id: $(
"input[name='" + product_element_name +
"']").val()
1845 }).done(
function (data) {
1847 selectbatch.empty();
1849 if (typeof data ==
"object") {
1850 console.log(
"data is already type object, no need to parse it");
1852 console.log(
"data is type "+(typeof data));
1853 data = JSON.parse(data);
1856 selectbatch.append($(
'<option>', {
1860 $.each(data,
function (key, value) {
1862 if(selectwarehouse.val() == -1) {
1863 var label = key +
" (<?php echo $langs->trans('Stock total') ?> : " + value +
")";
1865 var label = key +
" (<?php echo $langs->trans('Stock') ?> : " + value +
")";
1868 if(key === selectedbatch) {
1869 var option =
'<option value="'+key+
'" selected>'+ label +
'</option>';
1871 var option =
'<option value="'+key+
'">'+ label +
'</option>';
1874 selectbatch.append(option);
1880 function updateselectwarehousebybatch() {
1881 $(document).on(
'change',
'input[name*=batch]',
function(){
1882 console.log(
"We change batch so we update the list of possible warehouses");
1884 var selectbatch = $(
this);
1886 var selectwarehouse_name = selectbatch.attr(
'name').replace(
'batch',
'idwarehouse');
1887 var selectwarehouse = $(
"select[name*='" + selectwarehouse_name +
"']");
1888 var selectedwarehouse = selectwarehouse.val();
1890 if(selectedwarehouse != -1){
1894 var product_element_name = selectbatch.attr(
'name').replace(
'batch',
'product');
1898 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1900 action:
"updateselectwarehousebybatch",
1901 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1902 batch: $(
this).val(),
1903 token:
'<?php echo currentToken(); ?>',
1904 product_id: $(
"input[name='" + product_element_name +
"']").val()
1906 }).done(
function (data) {
1908 if (typeof data ==
"object") {
1909 console.log(
"data is already type object, no need to parse it");
1911 console.log(
"data is type "+(typeof data));
1912 data = JSON.parse(data);
1916 selectwarehouse.val(data).change();
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Class to manage warehouses.
Class to manage stock movements.
Class to manage predefined suppliers products.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class with list of lots and properties.
Class to manage projects.
Class to manage translations.
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
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_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
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.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier 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.