30require
'../main.inc.php';
31require_once DOL_DOCUMENT_ROOT.
'/bom/class/bom.class.php';
32require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formcompany.class.php';
33require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formfile.class.php';
34require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formprojet.class.php';
35require_once DOL_DOCUMENT_ROOT.
'/mrp/class/mo.class.php';
36require_once DOL_DOCUMENT_ROOT.
'/mrp/lib/mrp_mo.lib.php';
37require_once DOL_DOCUMENT_ROOT.
'/projet/class/project.class.php';
38require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
39require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
40require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
41require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/productlot.class.php';
42require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
43require_once DOL_DOCUMENT_ROOT.
'/workstation/class/workstation.class.php';
55$langs->loadLangs(array(
"mrp",
"stocks",
"other",
"product",
"productbatch"));
60$action =
GETPOST(
'action',
'aZ09');
61$confirm =
GETPOST(
'confirm',
'alpha');
62$cancel =
GETPOST(
'cancel',
'aZ09');
63$contextpage =
GETPOST(
'contextpage',
'aZ') ?
GETPOST(
'contextpage',
'aZ') :
'mocard';
64$backtopage =
GETPOST(
'backtopage',
'alpha');
67$fk_default_warehouse =
GETPOSTINT(
'fk_default_warehouse');
69$collapse =
GETPOST(
'collapse',
'aZ09comma');
74$diroutputmassaction =
$conf->mrp->dir_output.
'/temp/massgeneration/'.$user->id;
75$objectline =
new MoLine($db);
77$hookmanager->initHooks(array(
'moproduction',
'globalcard'));
80$extrafields->fetch_name_optionals_label(
$object->table_element);
82$search_array_options = $extrafields->getOptionalsFromPost(
$object->table_element,
'',
'search_');
85$search_all =
GETPOST(
"search_all",
'alpha');
87foreach (
$object->fields as $key => $val) {
88 if (
GETPOST(
'search_'.$key,
'alpha')) {
89 $search[$key] =
GETPOST(
'search_'.$key,
'alpha');
93if (empty($action) && empty($id) && empty($ref)) {
98include DOL_DOCUMENT_ROOT.
'/core/actions_fetchobject.inc.php';
103$isdraft = ((
$object->status == $object::STATUS_DRAFT) ? 1 : 0);
107$permissionnote = $user->hasRight(
'mrp',
'write');
108$permissiondellink = $user->hasRight(
'mrp',
'write');
109$permissiontoadd = $user->hasRight(
'mrp',
'write');
110$permissiontodelete = $user->hasRight(
'mrp',
'delete') || ($permissiontoadd && isset(
$object->status) &&
$object->status == $object::STATUS_DRAFT);
112$permissiontoproduce = $permissiontoadd;
113$permissiontoupdatecost = $user->hasRight(
'bom',
'read');
122$parameters = array();
123$reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
128if (empty($reshook)) {
131 $backurlforlist = DOL_URL_ROOT.
'/mrp/mo_list.php';
133 if (empty($backtopage) || ($cancel && empty($id))) {
135 if (empty($id) && (($action !=
'add' && $action !=
'create') || $cancel)) {
136 $backtopage = $backurlforlist;
138 $backtopage = DOL_URL_ROOT.
'/mrp/mo_production.php?id='.(
$id > 0 ?
$id :
'__ID__');
141 $triggermodname =
'MO_MODIFY';
143 if ($action ==
'confirm_cancel' && $confirm ==
'yes' && !empty($permissiontoadd)) {
144 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
145 $result =
$object->cancel($user, 0, $also_cancel_consumed_and_produced_lines);
147 header(
"Location: " . DOL_URL_ROOT.
'/mrp/mo_card.php?id=' .
$object->id);
153 } elseif ($action ==
'confirm_delete' && $confirm ==
'yes' && !empty($permissiontodelete)) {
154 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
155 $result =
$object->delete($user, 0, $also_cancel_consumed_and_produced_lines);
157 header(
"Location: " . $backurlforlist);
166 include DOL_DOCUMENT_ROOT.
'/core/actions_addupdatedelete.inc.php';
169 include DOL_DOCUMENT_ROOT.
'/core/actions_dellink.inc.php';
172 include DOL_DOCUMENT_ROOT.
'/core/actions_printing.inc.php';
175 $triggersendname =
'MO_SENTBYMAIL';
176 $autocopy =
'MAIN_MAIL_AUTOCOPY_MO_TO';
177 $trackid =
'mo'.$object->id;
178 include DOL_DOCUMENT_ROOT.
'/core/actions_sendmails.inc.php';
183 if ($action ==
'set_thirdparty' && $permissiontoadd) {
184 $object->setValueFrom(
'fk_soc',
GETPOSTINT(
'fk_soc'),
'',
null,
'date',
'', $user, $triggermodname);
186 if ($action ==
'classin' && $permissiontoadd) {
190 if ($action ==
'confirm_reopen' && $permissiontoadd) {
191 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_REOPEN');
194 if (($action ==
'confirm_addconsumeline' &&
GETPOST(
'addconsumelinebutton') && $permissiontoadd)
195 || ($action ==
'confirm_addproduceline' &&
GETPOST(
'addproducelinebutton') && $permissiontoadd)) {
196 $moline =
new MoLine($db);
201 $moline->fk_product =
GETPOSTINT(
'productidtoadd');
202 if (
GETPOST(
'addconsumelinebutton')) {
203 $moline->role =
'toconsume';
205 $moline->role =
'toproduce';
207 $moline->origin_type =
'free';
208 $moline->position = 0;
211 if (!empty($moline->fk_product)) {
212 $tmpproduct =
new Product($db);
213 $tmpproduct->fetch($moline->fk_product);
215 $moline->fk_default_workstation = $tmpproduct->fk_default_workstation;
216 $moline->disable_stock_change = 1;
217 if ($tmpproduct->duration_unit) {
218 $moline->qty = $tmpproduct->duration_value;
219 include_once DOL_DOCUMENT_ROOT.
'/core/class/cunits.class.php';
220 $cunits =
new CUnits($db);
221 $res = $cunits->fetch(0,
'', $tmpproduct->duration_unit,
'time');
223 $moline->fk_unit = $cunits->id;
227 $moline->disable_stock_change = 0;
229 $moline->fk_unit = $tmpproduct->fk_unit;
234 $extralabelsline = $extrafields->fetch_name_optionals_label(
$object->table_element_line);
235 $array_options = $extrafields->getOptionalsFromPost(
$object->table_element_line);
237 if (is_array($extralabelsline)) {
239 foreach ($extralabelsline as $key => $value) {
240 unset($_POST[
"options_".$key]);
243 if (is_array($array_options) && count($array_options) > 0) {
244 $moline->array_options = $array_options;
247 $resultline = $moline->create($user,
false);
248 if ($resultline <= 0) {
255 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
259 if (in_array($action, array(
'confirm_consumeorproduce',
'confirm_consumeandproduceall')) && $permissiontoproduce) {
262 $labelmovement =
GETPOST(
'inventorylabel',
'alphanohtml');
263 $codemovement =
GETPOST(
'inventorycode',
'alphanohtml');
268 foreach (
$object->lines as $line) {
269 if ($line->role ==
'toconsume') {
270 $tmpproduct =
new Product($db);
271 $tmpproduct->fetch($line->fk_product);
274 while (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
277 if ($qtytoprocess != 0) {
279 if (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i)) {
280 if (!(
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0)) {
281 $langs->load(
"errors");
282 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
285 if ($tmpproduct->status_batch && (!
GETPOST(
'batch-'.$line->id.
'-'.$i))) {
286 $langs->load(
"errors");
287 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
293 if (!$error &&
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0) {
295 $id_product_batch = 0;
297 $stockmove->context[
'mrp_role'] =
'toconsume';
299 if ($qtytoprocess >= 0) {
300 $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);
302 $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);
304 if ($idstockmove < 0) {
312 $moline =
new MoLine($db);
314 $moline->position = $pos;
315 $moline->fk_product = $line->fk_product;
316 $moline->fk_warehouse =
GETPOSTINT(
'idwarehouse-'.$line->id.
'-'.$i);
317 $moline->qty = $qtytoprocess;
318 $moline->batch =
GETPOST(
'batch-'.$line->id.
'-'.$i);
319 $moline->role =
'consumed';
320 $moline->fk_mrp_production = $line->id;
321 $moline->fk_stock_movement = $idstockmove == 0 ? null : $idstockmove;
322 $moline->fk_user_creat = $user->id;
324 $resultmoline = $moline->create($user);
325 if ($resultmoline <= 0) {
342 foreach (
$object->lines as $line) {
343 if ($line->role ==
'toproduce') {
344 $tmpproduct =
new Product($db);
345 $tmpproduct->fetch($line->fk_product);
348 while (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
349 $qtytoprocess = (float)
price2num(
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i));
350 $pricetoprocess =
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) ?
price2num(
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i)) : 0;
352 if ($qtytoprocess != 0) {
354 if (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i)) {
355 if (!(
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0)) {
356 $langs->load(
"errors");
357 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
360 if (isModEnabled(
'productbatch') && $tmpproduct->status_batch && (!
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i))) {
361 $langs->load(
"errors");
362 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
368 if (!$error &&
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0) {
370 $id_product_batch = 0;
371 $stockmove->origin_type =
$object->element;
372 $stockmove->origin_id =
$object->id;
373 $stockmove->context[
'mrp_role'] =
'toproduce';
375 $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);
376 if ($idstockmove < 0) {
384 $moline =
new MoLine($db);
386 $moline->position = $pos;
387 $moline->fk_product = $line->fk_product;
388 $moline->fk_warehouse =
GETPOSTINT(
'idwarehousetoproduce-'.$line->id.
'-'.$i);
389 $moline->qty = $qtytoprocess;
390 $moline->batch =
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i);
391 $moline->role =
'produced';
392 $moline->fk_mrp_production = $line->id;
393 $moline->fk_stock_movement = $idstockmove;
394 $moline->fk_user_creat = $user->id;
396 $resultmoline = $moline->create($user);
397 if ($resultmoline <= 0) {
412 $consumptioncomplete =
true;
413 $productioncomplete =
true;
416 foreach (
$object->lines as $line) {
417 if ($line->role ==
'toconsume') {
418 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
419 $alreadyconsumed = 0;
420 foreach ($arrayoflines as $line2) {
421 $alreadyconsumed += $line2[
'qty'];
424 if ($alreadyconsumed < $line->qty) {
425 $consumptioncomplete =
false;
428 if ($line->role ==
'toproduce') {
429 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
430 $alreadyproduced = 0;
431 foreach ($arrayoflines as $line2) {
432 $alreadyproduced += $line2[
'qty'];
435 if ($alreadyproduced < $line->qty) {
436 $productioncomplete =
false;
441 $consumptioncomplete =
false;
442 $productioncomplete =
false;
446 dol_syslog(
"consumptioncomplete = ".json_encode($consumptioncomplete).
" productioncomplete = ".json_encode($productioncomplete));
447 if ($consumptioncomplete && $productioncomplete) {
448 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
450 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_MO_PRODUCED');
459 $action = str_replace(
'confirm_',
'', $action);
465 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
471 if ($action ==
'confirm_produced' && $confirm ==
'yes' && $permissiontoadd) {
472 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
476 $outputlangs = $langs;
479 $newlang =
GETPOST(
'lang_id',
'aZ09');
482 $newlang =
$object->thirdparty->default_lang;
484 if (!empty($newlang)) {
486 $outputlangs->setDefaultLang($newlang);
491 $object->generateDocument($model, $outputlangs, 0, 0, 0);
498 if ($action ==
'confirm_editline' && $permissiontoadd) {
499 $moline =
new MoLine($db);
502 $extrafields->fetch_name_optionals_label($moline->element);
503 foreach ($extrafields->attributes[$moline->table_element][
'label'] as $key => $label) {
504 $value =
GETPOST(
'options_'.$key,
'alphanohtml');
505 $moline->array_options[
"options_".$key] = $value;
508 if (GETPOSTISSET(
'warehouse_lineProduce')) {
509 $moline->fk_warehouse = (
GETPOSTINT(
'warehouse_lineProduce') > 0 ?
GETPOSTINT(
'warehouse_lineProduce') : 0);
511 if (GETPOSTISSET(
'workstation_lineProduce')) {
512 $moline->fk_default_workstation = (
GETPOSTINT(
'workstation_lineProduce') > 0 ?
GETPOSTINT(
'workstation_lineProduce') : 0);
515 $res = $moline->update($user);
519 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
522 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
534$form =
new Form($db);
541$title = $langs->trans(
'Mo');
542$help_url =
'EN:Module_Manufacturing_Orders|FR:Module_Ordres_de_Fabrication|DE:Modul_Fertigungsauftrag';
543$morejs = array(
'/mrp/js/lib_dispatch.js.php');
544llxHeader(
'', $title, $help_url,
'', 0, 0, $morejs,
'',
'',
'mod-mrp page-card_production');
549if (
$object->id > 0 && (empty($action) || ($action !=
'edit' && $action !=
'create'))) {
550 $res =
$object->fetch_thirdparty();
551 $res =
$object->fetch_optionals();
554 $tmpwarehouse->fetch(
$object->fk_warehouse);
555 $fk_default_warehouse =
$object->fk_warehouse;
565 if ($action ==
'delete') {
566 $formquestion = array(
568 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
569 'name' =>
'alsoCancelConsumedAndProducedLines',
570 'type' =>
'checkbox',
574 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'DeleteMo'), $langs->trans(
'ConfirmDeleteMo'),
'confirm_delete', $formquestion, 0, 1);
577 if ($action ==
'deleteline') {
578 $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);
581 if ($action ==
'clone') {
583 $formquestion = array();
584 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'ToClone'), $langs->trans(
'ConfirmCloneMo',
$object->ref),
'confirm_clone', $formquestion,
'yes', 1);
588 if ($action ==
'validate') {
590 $ref = substr(
$object->ref, 1, 4);
591 if ($ref ==
'PROV') {
598 $text = $langs->trans(
'ConfirmValidateMo', $numref);
607 $formquestion = array();
608 if (isModEnabled(
'mrp')) {
610 require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
613 if (
$conf->browser->name ==
'ie') {
616 $formquestion = array(
623 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'Validate'), $text,
'confirm_validate', $formquestion, 0, 1, 220);
627 if ($action ==
'cancel') {
628 $formquestion = array(
630 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
631 'name' =>
'alsoCancelConsumedAndProducedLines',
632 'type' =>
'checkbox',
633 'value' => !
getDolGlobalString(
'MO_ALSO_CANCEL_CONSUMED_AND_PRODUCED_LINES_BY_DEFAULT') ? 0 : 1
636 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"] .
'?id=' .
$object->id, $langs->trans(
'CancelMo'), $langs->trans(
'ConfirmCancelMo'),
'confirm_cancel', $formquestion, 0, 1);
640 $parameters = array(
'formConfirm' => $formconfirm,
'lineid' => $lineid);
641 $reshook = $hookmanager->executeHooks(
'formConfirm', $parameters, $object, $action);
642 if (empty($reshook)) {
643 $formconfirm .= $hookmanager->resPrint;
644 } elseif ($reshook > 0) {
645 $formconfirm = $hookmanager->resPrint;
654 $linkback =
'<a href="'.DOL_URL_ROOT.
'/mrp/mo_list.php?restore_lastsearch_values=1'.(!empty($socid) ?
'&socid='.$socid :
'').
'">'.$langs->trans(
"BackToList").
'</a>';
656 $morehtmlref =
'<div class="refidno">';
665 if (is_object(
$object->thirdparty)) {
666 $morehtmlref .=
$object->thirdparty->getNomUrl(1,
'customer');
668 $morehtmlref .=
' (<a href="'.DOL_URL_ROOT.
'/commande/list.php?socid='.
$object->thirdparty->id.
'&search_societe='.urlencode(
$object->thirdparty->name).
'">'.$langs->trans(
"OtherOrders").
'</a>)';
673 if (isModEnabled(
'project')) {
674 $langs->load(
"projects");
675 if (is_object(
$object->thirdparty)) {
676 $morehtmlref .=
'<br>';
678 if ($permissiontoadd) {
679 $morehtmlref .=
img_picto($langs->trans(
"Project"),
'project',
'class="pictofixedwidth"');
680 if ($action !=
'classify') {
681 $morehtmlref .=
'<a class="editfielda" href="'.$_SERVER[
'PHP_SELF'].
'?action=classify&token='.
newToken().
'&id='.
$object->id.
'">'.
img_edit($langs->transnoentitiesnoconv(
'SetProject')).
'</a> ';
683 $morehtmlref .= $form->form_project($_SERVER[
'PHP_SELF'].
'?id='.
$object->id,
$object->socid,
$object->fk_project, ($action ==
'classify' ?
'projectid' :
'none'), 0, 0, 0, 1,
'',
'maxwidth300');
685 if (!empty(
$object->fk_project)) {
687 $proj->fetch(
$object->fk_project);
688 $morehtmlref .= $proj->getNomUrl(1);
690 $morehtmlref .=
'<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).
'</span>';
695 $morehtmlref .=
'</div>';
698 dol_banner_tab($object,
'ref', $linkback, 1,
'ref',
'ref', $morehtmlref);
701 print
'<div class="fichecenter">';
702 print
'<div class="fichehalfleft">';
703 print
'<div class="underbanner clearboth"></div>';
704 print
'<table class="border centpercent tableforfield">'.
"\n";
707 $keyforbreak =
'fk_warehouse';
708 unset(
$object->fields[
'fk_project']);
709 unset(
$object->fields[
'fk_soc']);
710 include DOL_DOCUMENT_ROOT.
'/core/tpl/commonfields_view.tpl.php';
713 include DOL_DOCUMENT_ROOT.
'/core/tpl/extrafields_view.tpl.php';
719 print
'<div class="clearboth"></div>';
724 if (!in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
725 print
'<div class="tabsAction">';
727 $parameters = array();
729 $reshook = $hookmanager->executeHooks(
'addMoreActionsButtons', $parameters, $object, $action);
730 if (empty($reshook)) {
732 if (
$object->status == $object::STATUS_DRAFT) {
733 if ($permissiontoadd) {
735 print
'<a class="butAction" href="'.$_SERVER[
'PHP_SELF'].
'?id='.
$object->id.
'&action=validate&token='.$newToken.
'">'.$langs->trans(
"Validate").
'</a>';
737 $langs->load(
"errors");
738 print
'<a class="butActionRefused" href="" title="'.$langs->trans(
"ErrorAddAtLeastOneLineFirst").
'">'.$langs->trans(
"Validate").
'</a>';
744 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
745 if ($permissiontoproduce) {
746 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeorproduce&token='.$newToken.
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
748 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
750 } elseif (
$object->status == Mo::STATUS_DRAFT) {
751 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
755 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
756 if ($permissiontoproduce) {
757 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeandproduceall&token='.$newToken.
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
759 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
761 } elseif (
$object->status == Mo::STATUS_DRAFT) {
762 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
766 if ($permissiontoadd) {
767 if (
$object->status == $object::STATUS_VALIDATED ||
$object->status == $object::STATUS_INPROGRESS) {
768 $arrayproduced =
$object->fetchLinesLinked(
'produced', 0);
770 foreach ($arrayproduced as $lineproduced) {
771 $nbProduced += $lineproduced[
'qty'];
773 if ($nbProduced > 0) {
774 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_produced&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
776 print
'<a class="butActionRefused" href="#" title="'.$langs->trans(
"GoOnTabProductionToProduceFirst", $langs->transnoentitiesnoconv(
"Production")).
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
779 print
'<a class="butActionDelete" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=cancel&token='.$newToken.
'">'.$langs->trans(
"Cancel").
'</a>'.
"\n";
782 if (
$object->status == $object::STATUS_CANCELED) {
783 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"ReOpen").
'</a>'.
"\n";
786 if (
$object->status == $object::STATUS_PRODUCED) {
787 if ($permissiontoproduce) {
788 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&token='.$newToken.
'">'.$langs->trans(
'ReOpen').
'</a>';
790 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ReOpen').
'</a>';
799 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline',
'addproduceline',
'editline'))) {
800 print
'<form method="POST" action="'.$_SERVER[
"PHP_SELF"].
'">';
801 print
'<input type="hidden" name="token" value="'.newToken().
'">';
802 print
'<input type="hidden" name="action" value="confirm_'.$action.
'">';
803 print
'<input type="hidden" name="backtopage" value="'.$backtopage.
'">';
804 print
'<input type="hidden" name="id" value="'.$id.
'">';
807 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
808 $defaultstockmovementlabel =
GETPOST(
'inventorylabel',
'alphanohtml') ?
GETPOST(
'inventorylabel',
'alphanohtml') : $langs->trans(
"ProductionForRef",
$object->
ref);
811 print
'<div class="center'.(in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) ?
' formconsumeproduce' :
'').
'">';
812 print
'<div class="opacitymedium hideonsmartphone paddingbottom">'.$langs->trans(
"ConfirmProductionDesc", $langs->transnoentitiesnoconv(
"Confirm")).
'<br></div>';
813 print
'<span class="fieldrequired">'.$langs->trans(
"InventoryCode").
':</span> <input type="text" class="minwidth150 maxwidth200" name="inventorycode" value="'.$defaultstockmovementcode.
'"> ';
814 print
'<span class="clearbothonsmartphone"></span>';
815 print $langs->trans(
"MovementLabel").
': <input type="text" class="minwidth300" name="inventorylabel" value="'.$defaultstockmovementlabel.
'"><br><br>';
816 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>';
817 print
'<input type="submit" class="button" value="'.$langs->trans(
"Confirm").
'" name="confirm">';
819 print
'<input class="button button-cancel" type="submit" value="'.$langs->trans(
"Cancel").
'" name="cancel">';
833 if (!empty(
$object->table_element_line)) {
840 $res = $bom->fetch(
$object->fk_bom);
842 $bom->calculateCosts();
843 $bomcost = $bom->unit_cost;
849 print
'<!-- Lines to consume -->'.
"\n";
850 print
'<div class="fichecenter">';
851 print
'<div class="fichehalfleft">';
852 print
'<div class="clearboth"></div>';
854 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addconsumeline&token='.
newToken();
855 $permissiontoaddaconsumeline = (
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED) ? 1 : -2;
856 $parameters = array(
'morecss' =>
'reposition');
858 if ($permissiontoaddaconsumeline == -2) {
859 $helpText = $langs->trans(
'MOIsClosed');
863 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
864 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewConsumeLines'), $helpText,
'fa fa-plus-circle size15x', $url,
'', $permissiontoaddaconsumeline, $parameters);
867 print
load_fiche_titre($langs->trans(
'Consumption'), $newcardbutton,
'', 0,
'',
'',
'');
869 print
'<div class="div-table-responsive-no-min">';
870 print
'<table class="noborder noshadow centpercent nobottom">';
872 print
'<!-- Line of title for products to consume -->'.
"\n";
873 print
'<tr class="liste_titre trheight5em">';
875 print
'<td>'.$langs->trans(
"Product").
'</td>';
877 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
882 print
'<td class="right">'.$langs->trans(
"UnitCost").
'</td>';
885 print
'<td class="right classfortooltip" title="'.$langs->trans(
"QtyAlreadyConsumed").
'">';
886 print $langs->trans(
"QtyAlreadyConsumedShort");
890 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
891 print $langs->trans(
"Warehouse");
892 if (isModEnabled(
'workstation')) {
893 print
' '.$langs->trans(
"or").
' '.$langs->trans(
"Workstation");
896 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
897 $listwarehouses = $tmpwarehouse->list_array(1);
898 if (count($listwarehouses) > 1) {
899 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, $langs->trans(
"ForceTo"), 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
900 } elseif (count($listwarehouses) == 1) {
901 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
907 if (isModEnabled(
'stock')) {
909 print
'<td align="right">';
910 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
911 print $langs->trans(
"Stock");
916 if (isModEnabled(
'productbatch')) {
918 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
919 print $langs->trans(
"Batch");
931 if (
$object->status == Mo::STATUS_DRAFT) {
936 if ($permissiontodelete) {
942 if ($action ==
'addconsumeline') {
943 print
'<!-- Add line to consume -->'.
"\n";
944 print
'<tr class="liste_titre">';
947 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth150');
950 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width40 right"></td>';
963 if (isModEnabled(
'stock')) {
966 if (isModEnabled(
'productbatch')) {
970 print
'<td colspan="'.$colspan.
'">';
971 print
'<input type="submit" class="button buttongen button-add" name="addconsumelinebutton" value="'.$langs->trans(
"Add").
'">';
972 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdconsumelinebutton" value="'.$langs->trans(
"Cancel").
'">';
977 if (
$object->status == Mo::STATUS_DRAFT) {
981 if ($permissiontodelete) {
987 if (is_object($objectline)) {
988 $extrafields->fetch_name_optionals_label(
$object->table_element_line);
989 $temps = $objectline->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
990 if (!empty($temps)) {
991 print
'<tr class="liste_titre"><td style="padding-top: 20px" colspan="9" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
1000 $bomcostupdated = 0;
1003 $nblinetoconsume = 0;
1004 foreach (
$object->lines as $line) {
1005 if ($line->role ==
'toconsume') {
1010 $nblinetoconsumecursor = 0;
1011 foreach (
$object->lines as $line) {
1012 if ($line->role ==
'toconsume') {
1013 $nblinetoconsumecursor++;
1015 $tmpproduct =
new Product($db);
1016 $tmpproduct->fetch($line->fk_product);
1017 $linecost =
price2num($tmpproduct->pmp,
'MT');
1021 $costprice =
price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp);
1022 if (empty($costprice)) {
1023 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1025 if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product) > 0) {
1026 $costprice = $productFournisseur->fourn_unitprice;
1034 if ($useunit && $line->fk_unit > 0) {
1036 $qtyhourservice = 0;
1037 if (preg_match(
'/^(\d+)([a-z]+)$/', $tmpproduct->duration, $reg)) {
1040 $qtyhourforline = 0;
1041 if ($line->fk_unit) {
1046 if ($qtyhourservice && $qtyhourforline) {
1047 $linecost =
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MT');
1048 $bomcostupdated +=
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MU');
1051 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1055 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1059 $bomcostupdated =
price2num($bomcostupdated,
'MU');
1060 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1061 $alreadyconsumed = 0;
1062 foreach ($arrayoflines as $line2) {
1063 $alreadyconsumed += $line2[
'qty'];
1066 if ($action ==
'editline' && $lineid == $line->id) {
1067 $linecost =
price2num($tmpproduct->pmp,
'MT');
1069 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1070 $alreadyconsumed = 0;
1071 if (is_array($arrayoflines) && !empty($arrayoflines)) {
1072 foreach ($arrayoflines as $line2) {
1073 $alreadyconsumed += $line2[
'qty'];
1076 $suffix =
'_' . $line->id;
1077 print
'<!-- Line to dispatch ' . $suffix .
' (line edited) -->' .
"\n";
1079 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1081 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1083 print
'<input name="lineid" type="hidden" value="' . $line->id .
'">';
1086 print
'<td>' . $tmpproduct->getNomUrl(1);
1087 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</span>';
1091 print
'<td class="right nowraponall">';
1092 print
'<input class="width40 right" name="qty_lineProduce" value="'. $line->qty.
'">';
1096 print
'<td class="right nowraponall">';
1104 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1109 print
'<td class="right">';
1110 print
' ' .
price2num($alreadyconsumed,
'MS');
1116 print $formproduct->selectWarehouses($line->fk_warehouse,
'warehouse_lineProduce',
'warehouseopen', 1);
1117 } elseif (isModEnabled(
'workstation')) {
1118 print $formproduct->selectWorkstations($line->fk_default_workstation,
'workstation_lineProduce', 1);
1123 if (isModEnabled(
'stock')) {
1124 print
'<td class="nowraponall right">';
1125 if ($tmpproduct->isStockManaged()) {
1126 if ($tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1127 print
img_warning($langs->trans(
'StockTooLow')).
' ';
1129 print
'<span class="left">'. $tmpproduct->stock_reel .
' </span>';
1135 if (isModEnabled(
'productbatch')) {
1139 print
'<td colspan="'.(3 + (
$object->status == Mo::STATUS_DRAFT ? 1 : 0) + ($permissiontodelete ? 1 : 0)).
'">';
1140 print
'<input type="submit" class="button buttongen button-add small nominwidth" name="save" value="' . $langs->trans(
"Save") .
'">';
1141 print
'<input type="submit" class="button buttongen button-cancel small nominwidth" name="cancel" value="' . $langs->trans(
"Cancel") .
'">';
1147 if (!empty($extrafields)) {
1148 $line->fetch_optionals();
1149 $temps = $line->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
1150 if (!empty($temps)) {
1152 print
'<tr><td colspan="'.$colspan.
'"><div style="padding-top: 20px" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
1154 print
'</div></td></tr>';
1158 $suffix =
'_' . $line->id;
1159 print
'<!-- Line to dispatch ' . $suffix .
' -->' .
"\n";
1161 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1162 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1164 print
'<tr data-line-id="' . $line->id .
'">';
1167 print
'<td>' . $tmpproduct->getNomUrl(1);
1168 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</div>';
1172 print
'<td class="right nowraponall">';
1174 if ($line->qty_frozen) {
1175 $help = ($help ?
'<br>' :
'') .
'<strong>' . $langs->trans(
"QuantityFrozen") .
'</strong>: ' .
yn(1) .
' (' . $langs->trans(
"QuantityConsumedInvariable") .
')';
1176 print $form->textwithpicto(
'', $help, -1,
'lock') .
' ';
1178 if ($line->disable_stock_change) {
1179 $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")) .
')';
1180 print $form->textwithpicto(
'', $help, -1,
'help') .
' ';
1186 print
'<td class="right nowraponall">';
1194 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1195 print
'<td class="right nowraponall">';
1196 print
price($linecost);
1201 print
'<td class="right">';
1202 if ($alreadyconsumed) {
1204 print
'jQuery(document).ready(function() {
1205 jQuery("#expandtoproduce' . $line->id .
'").click(function() {
1206 console.log("Expand mrp_production line ' . $line->id .
'");
1207 jQuery(".expanddetail' . $line->id .
'").toggle();';
1208 if ($nblinetoconsume == $nblinetoconsumecursor) {
1209 print
'if (jQuery("#tablelines").hasClass("nobottom")) { jQuery("#tablelines").removeClass("nobottom"); } else { jQuery("#tablelines").addClass("nobottom"); }';
1215 if (empty(
$conf->use_javascript_ajax)) {
1216 print
'<a href="' . $_SERVER[
"PHP_SELF"] .
'?collapse=' . $collapse .
',' . $line->id .
'">';
1218 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce' . $line->id .
'"');
1219 if (empty(
$conf->use_javascript_ajax)) {
1223 if ($nblinetoconsume == $nblinetoconsumecursor) {
1224 print
'<script>jQuery("#tablelines").removeClass("nobottom");</script>';
1227 print
' ' .
price2num($alreadyconsumed,
'MS');
1231 print
'<td class="tdoverflowmax100">';
1232 if ($tmpproduct->isStockManaged()) {
1234 if (
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') && $tmpwarehouse->id > 0) {
1235 print
img_picto(
'', $tmpwarehouse->picto) .
" " . $tmpwarehouse->label;
1237 if ($line->fk_warehouse > 0) {
1238 $warehouseline =
new Entrepot($db);
1239 $warehouseline->fetch($line->fk_warehouse);
1240 print $warehouseline->getNomUrl(1);
1244 if (isModEnabled(
'workstation') && $line->fk_default_workstation > 0) {
1246 $tmpworkstation->fetch($line->fk_default_workstation);
1247 print $tmpworkstation->getNomUrl(1);
1252 if (isModEnabled(
'stock')) {
1253 print
'<td class="nowraponall right">';
1255 if (!$line->disable_stock_change && $tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1256 print
img_warning($langs->trans(
'StockTooLow')) .
' ';
1258 if (!
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') || empty($tmpwarehouse->id)) {
1259 print
price2num($tmpproduct->stock_reel,
'MS');
1262 $tmpproduct->load_stock();
1263 $wh_stock = $tmpproduct->stock_warehouse[$tmpwarehouse->id];
1264 if (!empty($wh_stock)) {
1275 if (isModEnabled(
'productbatch')) {
1286 if (
$object->status == Mo::STATUS_DRAFT) {
1287 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1288 print
'<td class="center">';
1289 print
'<a class="reposition editfielda" href="' . $href .
'">';
1290 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1296 if ($permissiontodelete) {
1297 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=deleteline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1298 print
'<td class="center">';
1299 print
'<a class="reposition" href="' . $href .
'">';
1300 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1308 if (!empty($extrafields)) {
1309 $line->fetch_optionals();
1310 $temps = $line->showOptionals($extrafields,
'view', array(),
'',
'', 1,
'line');
1311 if (!empty($temps)) {
1313 print
'<tr><td colspan="'.$colspan.
'"><div id="extrafield_lines_area_'.$line->id.
'" name="extrafield_lines_area_'.$line->id.
'">';
1315 print
'</div></td></tr>';
1321 foreach ($arrayoflines as $line2) {
1322 print
'<tr class="expanddetail'.$line->id.
' hideobject opacitylow">';
1326 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1327 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1338 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1343 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1346 print
'<td class="tdoverflowmax150">';
1347 if ($line2[
'fk_warehouse'] > 0) {
1348 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1350 print $tmpwarehouse->getNomUrl(1);
1356 if (isModEnabled(
'stock')) {
1361 if (isModEnabled(
'productbatch')) {
1363 if ($line2[
'batch'] !=
'') {
1364 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1365 print $tmpbatch->getNomUrl(1);
1377 if (
$object->status == Mo::STATUS_DRAFT) {
1378 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line2[
'rowid']);
1379 print
'<td class="center">';
1380 print
'<a class="reposition" href="' . $href .
'">';
1381 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1387 if ($permissiontodelete) {
1388 $href = $_SERVER[
"PHP_SELF"].
'?id='.((int)
$object->id).
'&action=deleteline&token='.
newToken().
'&lineid='.((int) $line2[
'rowid']).
'&fk_movement='.((int) $line2[
'fk_stock_movement']);
1389 print
'<td class="center">';
1390 print
'<a class="reposition" href="'.$href.
'">';
1391 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1399 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1401 print
'<!-- Enter line to consume -->'.
"\n";
1403 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1405 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToConsume").
'</span></td>';
1406 $preselected = (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i) ?
GETPOST(
'qty-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyconsumed));
1407 if ($action ==
'consumeorproduce' && !
getDolGlobalString(
'MRP_AUTO_SET_REMAINING_QUANTITIES_TO_BE_CONSUMED') && !GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
1412 if (
getDolGlobalString(
'MRP_NEVER_CONSUME_MORE_THAN_EXPECTED') && ($line->qty - $alreadyconsumed) <= 0) {
1413 $disable =
'disabled';
1417 print
'<input type="hidden" name="product-'.$line->id.
'-'.$i.
'" value="'.$line->fk_product.
'">';
1420 print
'<td class="right"><input type="text" class="width50 right" id="qtytoconsume-' . $line->id .
'-' . $i .
'" name="qty-' . $line->id .
'-' . $i .
'" value="' . $preselected .
'" ' . $disable .
'></td>';
1426 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1436 if (empty($line->disable_stock_change)) {
1437 $preselected = (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) : ($tmpproduct->fk_default_warehouse > 0 ? $tmpproduct->fk_default_warehouse :
'ifone'));
1438 print $formproduct->selectWarehouses($preselected,
'idwarehouse-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0, array(),
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1440 print
'<span class="opacitymedium">'.$langs->trans(
"DisableStockChange").
'</span>';
1443 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1448 if (isModEnabled(
'stock')) {
1453 if (isModEnabled(
'productbatch')) {
1454 print
'<td class="nowraponall">';
1455 if ($tmpproduct->status_batch) {
1456 $preselected = (GETPOSTISSET(
'batch-'.$line->id.
'-'.$i) ?
GETPOST(
'batch-'.$line->id.
'-'.$i) :
'');
1457 print
'<input type="text" class="width75" name="batch-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'" list="batch-'.$line->id.
'-'.$i.
'">';
1458 print $formproduct->selectLotDataList(
'batch-'.$line->id.
'-'.$i, 0, $line->fk_product, 0, array());
1465 print
'<td align="right" class="split">';
1466 print
' '.img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.((int) $line->id).
', \''.
dol_escape_js($type).
'\', \
'qtymissingconsume\')"');
1470 print
'<td align="right" class="splitall">';
1471 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1472 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" data-max-qty="1" onClick="addDispatchLine('.$line->id.
', \'batch\', \'allmissingconsume\')"');
1477 if (
$object->status == Mo::STATUS_DRAFT) {
1482 if ($permissiontodelete) {
1496 print
'<script type="text/javascript">
1497 $(document).ready(function () {
1498 $("select[name=fk_default_warehouse]").change(function() {
1499 var fk_default_warehouse = $("option:selected", this).val();
1500 $("select[name^=idwarehouse-]").val(fk_default_warehouse).change();
1505 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) &&
1507 print
'<script>$(document).ready(function () {
1508 $("#fk_default_warehouse").change();
1516 print
'<div class="fichehalfright">';
1517 print
'<div class="clearboth"></div>';
1519 $nblinetoproduce = 0;
1520 foreach (
$object->lines as $line) {
1521 if ($line->role ==
'toproduce') {
1526 $newcardbutton =
'';
1527 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addproduceline&token='.
newToken();
1528 $permissiontoaddaproductline =
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED;
1529 $parameters = array(
'morecss' =>
'reposition');
1530 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
1531 if ($nblinetoproduce == 0 ||
$object->mrptype == 1) {
1532 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewProduceLines'),
'',
'fa fa-plus-circle size15x', $url,
'', (
int) $permissiontoaddaproductline, $parameters);
1536 print
load_fiche_titre($langs->trans(
'Production'), $newcardbutton,
'', 0,
'',
'');
1538 print
'<div class="div-table-responsive-no-min">';
1539 print
'<table id="tablelinestoproduce" class="noborder noshadow nobottom centpercent">';
1541 print
'<tr class="liste_titre trheight5em">';
1543 print
'<td>'.$langs->trans(
"Product").
'</td>';
1545 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
1548 print
'<td class="right">'.$langs->trans(
"Unit").
'</td>';
1551 if ($permissiontoupdatecost) {
1552 if (empty($bomcostupdated)) {
1553 print
'<td class="right classfortooltip" title="'.$langs->trans(
"AmountUsedToUpdateWAP").
'">';
1554 print $langs->trans(
"UnitCost");
1557 print
'<td class="right classfortooltip" title="'.$langs->trans(
"AmountUsedToUpdateWAP").
'">';
1558 print $langs->trans(
"ManufacturingPrice");
1563 print
'<td class="right classfortooltip" title="'.$langs->trans(
"QtyAlreadyProduced").
'">';
1564 print $langs->trans(
"QtyAlreadyProducedShort");
1568 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1569 print $langs->trans(
"Warehouse");
1574 if (isModEnabled(
'productbatch')) {
1576 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1577 print $langs->trans(
"Batch");
1589 if ($permissiontodelete) {
1595 if ($action ==
'addproduceline') {
1596 print
'<!-- Add line to produce -->'.
"\n";
1597 print
'<tr class="liste_titre">';
1601 print $form->select_produits(
'',
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
1604 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
1610 if ($permissiontoupdatecost) {
1614 print
'<td colspan="2">';
1615 print
'<input type="submit" class="button buttongen button-add" name="addproducelinebutton" value="'.$langs->trans(
"Add").
'">';
1616 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdproducelinebutton" value="'.$langs->trans(
"Cancel").
'">';
1619 if (isModEnabled(
'productbatch')) {
1629 if ($permissiontodelete) {
1636 $nblinetoproduce = 0;
1637 foreach (
$object->lines as $line) {
1638 if ($line->role ==
'toproduce') {
1643 $nblinetoproducecursor = 0;
1644 foreach (
$object->lines as $line) {
1645 if ($line->role ==
'toproduce') {
1648 $nblinetoproducecursor++;
1650 $tmpproduct =
new Product($db);
1651 $tmpproduct->fetch($line->fk_product);
1653 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
1654 $alreadyproduced = 0;
1655 foreach ($arrayoflines as $line2) {
1656 $alreadyproduced += $line2[
'qty'];
1659 $suffix =
'_'.$line->id;
1660 print
'<!-- Line to dispatch '.$suffix.
' (toproduce) -->'.
"\n";
1662 print
'<input id="qty_ordered'.$suffix.
'" type="hidden" value="'.$line->qty.
'">';
1663 print
'<input id="qty_dispatched'.$suffix.
'" type="hidden" value="'.$alreadyproduced.
'">';
1667 print
'<td>'.$tmpproduct->getNomUrl(1);
1668 print
'<br><span class="opacitymedium small">'.$tmpproduct->label.
'</span>';
1671 print
'<td class="right">'.$line->qty.
'</td>';
1674 print
'<td class="right">'.measuringUnitString($line->fk_unit,
'',
'', 1).
'</td>';
1677 if ($permissiontoupdatecost) {
1679 $manufacturingcost = 0;
1680 $manufacturingcostsrc =
'';
1682 $manufacturingcost = $bomcostupdated;
1683 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1684 if (empty($manufacturingcost)) {
1685 $manufacturingcost = $bomcost;
1686 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1688 if (empty($manufacturingcost)) {
1689 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1690 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1692 if (empty($manufacturingcost)) {
1693 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1694 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1698 print
'<td class="right nowraponall" title="'.dol_escape_htmltag($manufacturingcostsrc).
'">';
1699 if ($manufacturingcost) {
1700 print
price($manufacturingcost);
1705 print
'<td class="right nowraponall">';
1706 if ($alreadyproduced) {
1708 print
'jQuery(document).ready(function() {
1709 jQuery("#expandtoproduce'.$line->id.
'").click(function() {
1710 console.log("Expand mrp_production line '.$line->id.
'");
1711 jQuery(".expanddetailtoproduce'.$line->id.
'").toggle();';
1712 if ($nblinetoproduce == $nblinetoproducecursor) {
1713 print
'if (jQuery("#tablelinestoproduce").hasClass("nobottom")) { jQuery("#tablelinestoproduce").removeClass("nobottom"); } else { jQuery("#tablelinestoproduce").addClass("nobottom"); }';
1719 if (empty(
$conf->use_javascript_ajax)) {
1720 print
'<a href="'.$_SERVER[
"PHP_SELF"].
'?collapse='.$collapse.
','.$line->id.
'">';
1722 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce'.$line->id.
'"');
1723 if (empty(
$conf->use_javascript_ajax)) {
1727 print
' '.$alreadyproduced;
1733 if (isModEnabled(
'productbatch')) {
1743 if ($permissiontodelete) {
1744 if ($line->origin_type ==
'free') {
1745 $href = $_SERVER[
"PHP_SELF"];
1746 $href .=
'?id='.$object->id;
1747 $href .=
'&action=deleteline';
1748 $href .=
'&token='.newToken();
1749 $href .=
'&lineid='.$line->id;
1750 print
'<td class="center">';
1751 print
'<a class="reposition" href="'.$href.
'">';
1752 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
"delete");
1762 foreach ($arrayoflines as $line2) {
1763 print
'<tr class="expanddetailtoproduce'.$line->id.
' hideobject opacitylow">';
1766 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1767 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1777 if ($permissiontoupdatecost) {
1781 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1783 print
'<td class="tdoverflowmax150">';
1784 if ($line2[
'fk_warehouse'] > 0) {
1785 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1787 print $tmpwarehouse->getNomUrl(1);
1792 if (isModEnabled(
'productbatch')) {
1794 if ($line2[
'batch'] !=
'') {
1795 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1796 print $tmpbatch->getNomUrl(1);
1807 if ($permissiontodelete) {
1813 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1814 print
'<!-- Enter line to produce -->'.
"\n";
1816 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1818 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToProduce").
'</span></td>';
1819 $preselected = (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyproduced));
1820 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
1824 print
'<td class="right"><input type="text" class="width50 right" id="qtytoproduce-'.$line->id.
'-'.$i.
'" name="qtytoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1827 print
'<td class="right"></td>';
1830 if ($permissiontoupdatecost) {
1832 $manufacturingcost = 0;
1833 $manufacturingcostsrc =
'';
1835 $manufacturingcost = $bomcostupdated;
1836 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1837 if (empty($manufacturingcost)) {
1838 $manufacturingcost = $bomcost;
1839 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1841 if (empty($manufacturingcost)) {
1842 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1843 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1845 if (empty($manufacturingcost)) {
1846 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1847 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1852 $preselected = (GETPOSTISSET(
'pricetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) : ($manufacturingcost ?
price($manufacturingcost) :
''));
1853 print
'<td class="right"><input type="text" class="width75 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1855 print
'<td><input type="hidden" class="width50 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.($manufacturingcost ? $manufacturingcost :
'').
'"></td>';
1863 $preselected = (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) : (
$object->fk_warehouse > 0 ?
$object->fk_warehouse :
'ifone'));
1864 print $formproduct->selectWarehouses($preselected,
'idwarehousetoproduce-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0, array(),
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1866 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1870 if (isModEnabled(
'productbatch')) {
1872 if ($tmpproduct->status_batch) {
1873 $preselected = (GETPOSTISSET(
'batchtoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i) :
'');
1874 print
'<input type="text" class="width75" name="batchtoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'">';
1878 if ($tmpproduct->status_batch) {
1880 print
'<td align="right" class="split">';
1881 print
img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.$line->id.
', \''.$type.
'\', \
'qtymissing\')"');
1884 print
'<td align="right" class="splitall">';
1885 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1886 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" onClick="addDispatchLine('.$line->id.
', \'batch\', \'alltoproduce\')"');
1912 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline'))) {
1916 <script
type=
"text/javascript" language=
"javascript">
1918 $(document).ready(
function() {
1920 updateselectbatchbywarehouse();
1922 updateselectwarehousebybatch();
1925 function updateselectbatchbywarehouse() {
1926 $(document).on(
'change',
"select[name*='idwarehouse']",
function () {
1927 console.log(
"We change warehouse so we update the list of possible batch number");
1929 var selectwarehouse = $(
this);
1931 var selectbatch_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'batch');
1932 var selectbatch = $(
"datalist[id*='" + selectbatch_name +
"']");
1933 var selectedbatch = selectbatch.val();
1935 var product_element_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'product');
1939 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1941 action:
"updateselectbatchbywarehouse",
1942 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1943 warehouse_id: $(
this).val(),
1944 token:
'<?php echo currentToken(); ?>',
1945 product_id: $(
"input[name='" + product_element_name +
"']").val()
1947 }).done(
function (data) {
1949 selectbatch.empty();
1951 if (typeof data ==
"object") {
1952 console.log(
"data is already type object, no need to parse it");
1954 console.log(
"data is type "+(typeof data));
1955 data = JSON.parse(data);
1958 selectbatch.append($(
'<option>', {
1962 $.each(data,
function (key, value) {
1964 if(selectwarehouse.val() == -1) {
1965 var label = key +
" (<?php echo $langs->trans('Stock total') ?> : " + value +
")";
1967 var label = key +
" (<?php echo $langs->trans('Stock') ?> : " + value +
")";
1970 if(key === selectedbatch) {
1971 var option =
'<option value="'+key+
'" selected>'+ label +
'</option>';
1973 var option =
'<option value="'+key+
'">'+ label +
'</option>';
1976 selectbatch.append(option);
1982 function updateselectwarehousebybatch() {
1983 $(document).on(
'change',
'input[name*=batch]',
function(){
1984 console.log(
"We change batch so we update the list of possible warehouses");
1986 var selectbatch = $(
this);
1988 var selectwarehouse_name = selectbatch.attr(
'name').replace(
'batch',
'idwarehouse');
1989 var selectwarehouse = $(
"select[name*='" + selectwarehouse_name +
"']");
1990 var selectedwarehouse = selectwarehouse.val();
1992 if(selectedwarehouse != -1){
1996 var product_element_name = selectbatch.attr(
'name').replace(
'batch',
'product');
2000 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
2002 action:
"updateselectwarehousebybatch",
2003 permissiontoproduce: <?php echo $permissiontoproduce ?>,
2004 batch: $(
this).val(),
2005 token:
'<?php echo currentToken(); ?>',
2006 product_id: $(
"input[name='" + product_element_name +
"']").val()
2008 }).done(
function (data) {
2010 if (typeof data ==
"object") {
2011 console.log(
"data is already type object, no need to parse it");
2013 console.log(
"data is type "+(typeof data));
2014 data = JSON.parse(data);
2018 selectwarehouse.val(data).change();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
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 of dictionary type of thirdparty (used by imports)
Class to manage warehouses.
Class to manage stock movements.
Class to manage predefined suppliers products.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class with list of lots and properties.
Class to manage projects.
Class to manage translations.
convertDurationtoHour($duration_value, $duration_unit)
Convert duration to hour.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
newToken()
Return the value of token currently saved into session with name 'newtoken'.
yn($yesno, $format=1, $color=0)
Return yes or no in current language.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='')
Return the value of a $_GET or $_POST supervariable, converted into float.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
moPrepareHead($object)
Prepare array of tabs for Mo.
measuringUnitString($unitid, $measuring_style='', $unitscale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.