31require
'../main.inc.php';
32require_once DOL_DOCUMENT_ROOT.
'/bom/class/bom.class.php';
33require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formcompany.class.php';
34require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formfile.class.php';
35require_once DOL_DOCUMENT_ROOT.
'/core/class/html.formprojet.class.php';
36require_once DOL_DOCUMENT_ROOT.
'/mrp/class/mo.class.php';
37require_once DOL_DOCUMENT_ROOT.
'/mrp/lib/mrp_mo.lib.php';
38require_once DOL_DOCUMENT_ROOT.
'/projet/class/project.class.php';
39require_once DOL_DOCUMENT_ROOT.
'/product/class/product.class.php';
40require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
41require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/entrepot.class.php';
42require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/productlot.class.php';
43require_once DOL_DOCUMENT_ROOT.
'/product/stock/class/mouvementstock.class.php';
44require_once DOL_DOCUMENT_ROOT.
'/workstation/class/workstation.class.php';
56$langs->loadLangs(array(
"mrp",
"stocks",
"other",
"product",
"productbatch"));
61$action =
GETPOST(
'action',
'aZ09');
62$confirm =
GETPOST(
'confirm',
'alpha');
63$cancel =
GETPOST(
'cancel',
'aZ09');
64$contextpage =
GETPOST(
'contextpage',
'aZ') ?
GETPOST(
'contextpage',
'aZ') :
'mocard';
65$backtopage =
GETPOST(
'backtopage',
'alpha');
68$fk_default_warehouse =
GETPOSTINT(
'fk_default_warehouse');
70$collapse =
GETPOST(
'collapse',
'aZ09comma');
75$diroutputmassaction =
$conf->mrp->dir_output.
'/temp/massgeneration/'.$user->id;
76$objectline =
new MoLine($db);
78$hookmanager->initHooks(array(
'moproduction',
'globalcard'));
81$extrafields->fetch_name_optionals_label(
$object->table_element);
83$search_array_options = $extrafields->getOptionalsFromPost(
$object->table_element,
'',
'search_');
86$search_all =
GETPOST(
"search_all",
'alpha');
88foreach (
$object->fields as $key => $val) {
89 if (
GETPOST(
'search_'.$key,
'alpha')) {
90 $search[$key] =
GETPOST(
'search_'.$key,
'alpha');
94if (empty($action) && empty($id) && empty($ref)) {
99include DOL_DOCUMENT_ROOT.
'/core/actions_fetchobject.inc.php';
104$isdraft = ((
$object->status == $object::STATUS_DRAFT) ? 1 : 0);
108$permissionnote = $user->hasRight(
'mrp',
'write');
109$permissiondellink = $user->hasRight(
'mrp',
'write');
110$permissiontoadd = $user->hasRight(
'mrp',
'write');
111$permissiontodelete = $user->hasRight(
'mrp',
'delete') || ($permissiontoadd && isset(
$object->status) &&
$object->status == $object::STATUS_DRAFT);
113$permissiontoproduce = $permissiontoadd;
114$permissiontoupdatecost = $user->hasRight(
'bom',
'read');
123$parameters = array();
124$reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
129if (empty($reshook)) {
132 $backurlforlist = DOL_URL_ROOT.
'/mrp/mo_list.php';
134 if (empty($backtopage) || ($cancel && empty($id))) {
136 if (empty($id) && (($action !=
'add' && $action !=
'create') || $cancel)) {
137 $backtopage = $backurlforlist;
139 $backtopage = DOL_URL_ROOT.
'/mrp/mo_production.php?id='.(
$id > 0 ?
$id :
'__ID__');
142 $triggermodname =
'MO_MODIFY';
144 if ($action ==
'confirm_cancel' && $confirm ==
'yes' && !empty($permissiontoadd)) {
145 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
146 $result =
$object->cancel($user, 0, $also_cancel_consumed_and_produced_lines);
148 header(
"Location: " . DOL_URL_ROOT.
'/mrp/mo_card.php?id=' .
$object->id);
154 } elseif ($action ==
'confirm_delete' && $confirm ==
'yes' && !empty($permissiontodelete)) {
155 $also_cancel_consumed_and_produced_lines = (
GETPOST(
'alsoCancelConsumedAndProducedLines',
'alpha') ? 1 : 0);
156 $result =
$object->delete($user, 0, $also_cancel_consumed_and_produced_lines);
158 header(
"Location: " . $backurlforlist);
167 include DOL_DOCUMENT_ROOT.
'/core/actions_addupdatedelete.inc.php';
170 include DOL_DOCUMENT_ROOT.
'/core/actions_dellink.inc.php';
173 include DOL_DOCUMENT_ROOT.
'/core/actions_printing.inc.php';
176 $triggersendname =
'MO_SENTBYMAIL';
177 $autocopy =
'MAIN_MAIL_AUTOCOPY_MO_TO';
178 $trackid =
'mo'.$object->id;
179 include DOL_DOCUMENT_ROOT.
'/core/actions_sendmails.inc.php';
184 if ($action ==
'set_thirdparty' && $permissiontoadd) {
185 $object->setValueFrom(
'fk_soc',
GETPOSTINT(
'fk_soc'),
'',
null,
'date',
'', $user, $triggermodname);
187 if ($action ==
'classin' && $permissiontoadd) {
191 if ($action ==
'confirm_reopen' && $permissiontoadd) {
192 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_REOPEN');
195 if (($action ==
'confirm_addconsumeline' &&
GETPOST(
'addconsumelinebutton') && $permissiontoadd)
196 || ($action ==
'confirm_addproduceline' &&
GETPOST(
'addproducelinebutton') && $permissiontoadd)) {
197 $moline =
new MoLine($db);
202 $moline->fk_product =
GETPOSTINT(
'productidtoadd');
203 if (
GETPOST(
'addconsumelinebutton')) {
204 $moline->role =
'toconsume';
206 $moline->role =
'toproduce';
208 $moline->origin_type =
'free';
209 $moline->position = 0;
212 if (!empty($moline->fk_product)) {
213 $tmpproduct =
new Product($db);
214 $tmpproduct->fetch($moline->fk_product);
216 $moline->fk_default_workstation = $tmpproduct->fk_default_workstation;
217 $moline->disable_stock_change = 1;
218 if ($tmpproduct->duration_unit) {
219 $moline->qty = $tmpproduct->duration_value;
220 include_once DOL_DOCUMENT_ROOT.
'/core/class/cunits.class.php';
221 $cunits =
new CUnits($db);
222 $res = $cunits->fetch(0,
'', $tmpproduct->duration_unit,
'time');
224 $moline->fk_unit = $cunits->id;
228 $moline->disable_stock_change = 0;
230 $moline->fk_unit = $tmpproduct->fk_unit;
235 $extralabelsline = $extrafields->fetch_name_optionals_label(
$object->table_element_line);
236 $array_options = $extrafields->getOptionalsFromPost(
$object->table_element_line);
238 if (is_array($extralabelsline)) {
240 foreach ($extralabelsline as $key => $value) {
241 unset($_POST[
"options_".$key]);
244 if (is_array($array_options) && count($array_options) > 0) {
245 $moline->array_options = $array_options;
248 $resultline = $moline->create($user,
false);
249 if ($resultline <= 0) {
256 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
260 if (in_array($action, array(
'confirm_consumeorproduce',
'confirm_consumeandproduceall')) && $permissiontoproduce) {
263 $labelmovement =
GETPOST(
'inventorylabel',
'alphanohtml');
264 $codemovement =
GETPOST(
'inventorycode',
'alphanohtml');
269 foreach (
$object->lines as $line) {
270 if ($line->role ==
'toconsume') {
271 $tmpproduct =
new Product($db);
272 $tmpproduct->fetch($line->fk_product);
275 while (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
278 if ($qtytoprocess != 0) {
280 if (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i)) {
281 if (!(
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0)) {
282 $langs->load(
"errors");
283 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
286 if ($tmpproduct->status_batch && (!
GETPOST(
'batch-'.$line->id.
'-'.$i))) {
287 $langs->load(
"errors");
288 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
294 if (!$error &&
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) > 0) {
296 $id_product_batch = 0;
298 $stockmove->context[
'mrp_role'] =
'toconsume';
300 if ($qtytoprocess >= 0) {
301 $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);
303 $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);
305 if ($idstockmove < 0) {
313 $moline =
new MoLine($db);
315 $moline->position = $pos;
316 $moline->fk_product = $line->fk_product;
317 $moline->fk_warehouse =
GETPOSTINT(
'idwarehouse-'.$line->id.
'-'.$i);
318 $moline->qty = $qtytoprocess;
319 $moline->batch =
GETPOST(
'batch-'.$line->id.
'-'.$i);
320 $moline->role =
'consumed';
321 $moline->fk_mrp_production = $line->id;
322 $moline->fk_stock_movement = $idstockmove == 0 ? null : $idstockmove;
323 $moline->fk_user_creat = $user->id;
325 $resultmoline = $moline->create($user);
326 if ($resultmoline <= 0) {
343 foreach (
$object->lines as $line) {
344 if ($line->role ==
'toproduce') {
345 $tmpproduct =
new Product($db);
346 $tmpproduct->fetch($line->fk_product);
349 while (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
350 $qtytoprocess = (float)
price2num(
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i));
351 $pricetoprocess =
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) ?
price2num(
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i)) : 0;
353 if ($qtytoprocess != 0) {
355 if (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i)) {
356 if (!(
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0)) {
357 $langs->load(
"errors");
358 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Warehouse"), $tmpproduct->ref),
null,
'errors');
361 if (isModEnabled(
'productbatch') && $tmpproduct->status_batch && (!
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i))) {
362 $langs->load(
"errors");
363 setEventMessages($langs->trans(
"ErrorFieldRequiredForProduct", $langs->transnoentitiesnoconv(
"Batch"), $tmpproduct->ref),
null,
'errors');
369 if (!$error &&
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) > 0) {
371 $id_product_batch = 0;
372 $stockmove->origin_type =
$object->element;
373 $stockmove->origin_id =
$object->id;
374 $stockmove->context[
'mrp_role'] =
'toproduce';
376 $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);
377 if ($idstockmove < 0) {
385 $moline =
new MoLine($db);
387 $moline->position = $pos;
388 $moline->fk_product = $line->fk_product;
389 $moline->fk_warehouse =
GETPOSTINT(
'idwarehousetoproduce-'.$line->id.
'-'.$i);
390 $moline->qty = $qtytoprocess;
391 $moline->batch =
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i);
392 $moline->role =
'produced';
393 $moline->fk_mrp_production = $line->id;
394 $moline->fk_stock_movement = $idstockmove;
395 $moline->fk_user_creat = $user->id;
397 $resultmoline = $moline->create($user);
398 if ($resultmoline <= 0) {
413 $consumptioncomplete =
true;
414 $productioncomplete =
true;
417 foreach (
$object->lines as $line) {
418 if ($line->role ==
'toconsume') {
419 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
420 $alreadyconsumed = 0;
421 foreach ($arrayoflines as $line2) {
422 $alreadyconsumed += $line2[
'qty'];
425 if ($alreadyconsumed < $line->qty) {
426 $consumptioncomplete =
false;
429 if ($line->role ==
'toproduce') {
430 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
431 $alreadyproduced = 0;
432 foreach ($arrayoflines as $line2) {
433 $alreadyproduced += $line2[
'qty'];
436 if ($alreadyproduced < $line->qty) {
437 $productioncomplete =
false;
442 $consumptioncomplete =
false;
443 $productioncomplete =
false;
447 dol_syslog(
"consumptioncomplete = ".json_encode($consumptioncomplete).
" productioncomplete = ".json_encode($productioncomplete));
448 if ($consumptioncomplete && $productioncomplete) {
449 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
451 $result =
$object->setStatut($object::STATUS_INPROGRESS, 0,
'',
'MRP_MO_PRODUCED');
460 $action = str_replace(
'confirm_',
'', $action);
466 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
472 if ($action ==
'confirm_produced' && $confirm ==
'yes' && $permissiontoadd) {
473 $result =
$object->setStatut($object::STATUS_PRODUCED, 0,
'',
'MRP_MO_PRODUCED');
477 $outputlangs = $langs;
480 $newlang =
GETPOST(
'lang_id',
'aZ09');
483 $newlang =
$object->thirdparty->default_lang;
485 if (!empty($newlang)) {
487 $outputlangs->setDefaultLang($newlang);
492 $object->generateDocument($model, $outputlangs, 0, 0, 0);
499 if ($action ==
'confirm_editline' && $permissiontoadd) {
500 $moline =
new MoLine($db);
503 $extrafields->fetch_name_optionals_label($moline->element);
504 foreach ($extrafields->attributes[$moline->table_element][
'label'] as $key => $label) {
505 $value =
GETPOST(
'options_'.$key,
'alphanohtml');
506 $moline->array_options[
"options_".$key] = $value;
509 if (GETPOSTISSET(
'warehouse_lineProduce')) {
510 $moline->fk_warehouse = (
GETPOSTINT(
'warehouse_lineProduce') > 0 ?
GETPOSTINT(
'warehouse_lineProduce') : 0);
512 if (GETPOSTISSET(
'workstation_lineProduce')) {
513 $moline->fk_default_workstation = (
GETPOSTINT(
'workstation_lineProduce') > 0 ?
GETPOSTINT(
'workstation_lineProduce') : 0);
516 $res = $moline->update($user);
520 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
523 header(
"Location: ".$_SERVER[
"PHP_SELF"].
'?id='.
$object->id);
535$form =
new Form($db);
542$title = $langs->trans(
'Mo');
543$help_url =
'EN:Module_Manufacturing_Orders|FR:Module_Ordres_de_Fabrication|DE:Modul_Fertigungsauftrag';
544$morejs = array(
'/mrp/js/lib_dispatch.js.php');
545llxHeader(
'', $title, $help_url,
'', 0, 0, $morejs,
'',
'',
'mod-mrp page-card_production');
550if (
$object->id > 0 && (empty($action) || ($action !=
'edit' && $action !=
'create'))) {
551 $res =
$object->fetch_thirdparty();
552 $res =
$object->fetch_optionals();
555 $tmpwarehouse->fetch(
$object->fk_warehouse);
556 $fk_default_warehouse =
$object->fk_warehouse;
566 if ($action ==
'delete') {
567 $formquestion = array(
569 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
570 'name' =>
'alsoCancelConsumedAndProducedLines',
571 'type' =>
'checkbox',
575 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'DeleteMo'), $langs->trans(
'ConfirmDeleteMo'),
'confirm_delete', $formquestion, 0, 1);
578 if ($action ==
'deleteline') {
579 $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);
582 if ($action ==
'clone') {
584 $formquestion = array();
585 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'ToClone'), $langs->trans(
'ConfirmCloneMo',
$object->ref),
'confirm_clone', $formquestion,
'yes', 1);
589 if ($action ==
'validate') {
591 $ref = substr(
$object->ref, 1, 4);
592 if ($ref ==
'PROV') {
599 $text = $langs->trans(
'ConfirmValidateMo', $numref);
608 $formquestion = array();
609 if (isModEnabled(
'mrp')) {
611 require_once DOL_DOCUMENT_ROOT.
'/product/class/html.formproduct.class.php';
614 if (
$conf->browser->name ==
'ie') {
617 $formquestion = array(
624 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?id='.
$object->id, $langs->trans(
'Validate'), $text,
'confirm_validate', $formquestion, 0, 1, 220);
628 if ($action ==
'cancel') {
629 $formquestion = array(
631 'label' => $langs->trans(
'MoCancelConsumedAndProducedLines'),
632 'name' =>
'alsoCancelConsumedAndProducedLines',
633 'type' =>
'checkbox',
634 'value' => !
getDolGlobalString(
'MO_ALSO_CANCEL_CONSUMED_AND_PRODUCED_LINES_BY_DEFAULT') ? 0 : 1
637 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"] .
'?id=' .
$object->id, $langs->trans(
'CancelMo'), $langs->trans(
'ConfirmCancelMo'),
'confirm_cancel', $formquestion, 0, 1);
641 $parameters = array(
'formConfirm' => $formconfirm,
'lineid' => $lineid);
642 $reshook = $hookmanager->executeHooks(
'formConfirm', $parameters, $object, $action);
643 if (empty($reshook)) {
644 $formconfirm .= $hookmanager->resPrint;
645 } elseif ($reshook > 0) {
646 $formconfirm = $hookmanager->resPrint;
655 $linkback =
'<a href="'.DOL_URL_ROOT.
'/mrp/mo_list.php?restore_lastsearch_values=1'.(!empty($socid) ?
'&socid='.$socid :
'').
'">'.$langs->trans(
"BackToList").
'</a>';
657 $morehtmlref =
'<div class="refidno">';
666 if (is_object(
$object->thirdparty)) {
667 $morehtmlref .=
$object->thirdparty->getNomUrl(1,
'customer');
669 $morehtmlref .=
' (<a href="'.DOL_URL_ROOT.
'/commande/list.php?socid='.
$object->thirdparty->id.
'&search_societe='.urlencode(
$object->thirdparty->name).
'">'.$langs->trans(
"OtherOrders").
'</a>)';
674 if (isModEnabled(
'project')) {
675 $langs->load(
"projects");
676 if (is_object(
$object->thirdparty)) {
677 $morehtmlref .=
'<br>';
679 if ($permissiontoadd) {
680 $morehtmlref .=
img_picto($langs->trans(
"Project"),
'project',
'class="pictofixedwidth"');
681 if ($action !=
'classify') {
682 $morehtmlref .=
'<a class="editfielda" href="'.$_SERVER[
'PHP_SELF'].
'?action=classify&token='.
newToken().
'&id='.
$object->id.
'">'.
img_edit($langs->transnoentitiesnoconv(
'SetProject')).
'</a> ';
684 $morehtmlref .= $form->form_project($_SERVER[
'PHP_SELF'].
'?id='.
$object->id,
$object->socid,
$object->fk_project, ($action ==
'classify' ?
'projectid' :
'none'), 0, 0, 0, 1,
'',
'maxwidth300');
686 if (!empty(
$object->fk_project)) {
688 $proj->fetch(
$object->fk_project);
689 $morehtmlref .= $proj->getNomUrl(1);
691 $morehtmlref .=
'<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).
'</span>';
696 $morehtmlref .=
'</div>';
699 dol_banner_tab($object,
'ref', $linkback, 1,
'ref',
'ref', $morehtmlref);
702 print
'<div class="fichecenter">';
703 print
'<div class="fichehalfleft">';
704 print
'<div class="underbanner clearboth"></div>';
705 print
'<table class="border centpercent tableforfield">'.
"\n";
708 $keyforbreak =
'fk_warehouse';
709 unset(
$object->fields[
'fk_project']);
710 unset(
$object->fields[
'fk_soc']);
711 include DOL_DOCUMENT_ROOT.
'/core/tpl/commonfields_view.tpl.php';
714 include DOL_DOCUMENT_ROOT.
'/core/tpl/extrafields_view.tpl.php';
720 print
'<div class="clearboth"></div>';
725 if (!in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
726 print
'<div class="tabsAction">';
728 $parameters = array();
730 $reshook = $hookmanager->executeHooks(
'addMoreActionsButtons', $parameters, $object, $action);
731 if (empty($reshook)) {
733 if (
$object->status == $object::STATUS_DRAFT) {
734 if ($permissiontoadd) {
736 print
'<a class="butAction" href="'.$_SERVER[
'PHP_SELF'].
'?id='.
$object->id.
'&action=validate&token='.$newToken.
'">'.$langs->trans(
"Validate").
'</a>';
738 $langs->load(
"errors");
739 print
'<a class="butActionRefused" href="" title="'.$langs->trans(
"ErrorAddAtLeastOneLineFirst").
'">'.$langs->trans(
"Validate").
'</a>';
745 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
746 if ($permissiontoproduce) {
747 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeorproduce&token='.$newToken.
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
749 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
751 } elseif (
$object->status == Mo::STATUS_DRAFT) {
752 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeOrProduce').
'</a>';
756 if (
$object->status == Mo::STATUS_VALIDATED ||
$object->status == Mo::STATUS_INPROGRESS) {
757 if ($permissiontoproduce) {
758 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=consumeandproduceall&token='.$newToken.
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
760 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
762 } elseif (
$object->status == Mo::STATUS_DRAFT) {
763 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"ValidateBefore").
'">'.$langs->trans(
'ConsumeAndProduceAll').
'</a>';
767 if ($permissiontoadd) {
768 if (
$object->status == $object::STATUS_VALIDATED ||
$object->status == $object::STATUS_INPROGRESS) {
769 $arrayproduced =
$object->fetchLinesLinked(
'produced', 0);
771 foreach ($arrayproduced as $lineproduced) {
772 $nbProduced += $lineproduced[
'qty'];
774 if ($nbProduced > 0) {
775 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_produced&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
777 print
'<a class="butActionRefused" href="#" title="'.$langs->trans(
"GoOnTabProductionToProduceFirst", $langs->transnoentitiesnoconv(
"Production")).
'">'.$langs->trans(
"Close").
'</a>'.
"\n";
780 print
'<a class="butActionDelete" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=cancel&token='.$newToken.
'">'.$langs->trans(
"Cancel").
'</a>'.
"\n";
783 if (
$object->status == $object::STATUS_CANCELED) {
784 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&confirm=yes&token='.$newToken.
'">'.$langs->trans(
"ReOpen").
'</a>'.
"\n";
787 if (
$object->status == $object::STATUS_PRODUCED) {
788 if ($permissiontoproduce) {
789 print
'<a class="butAction" href="'.$_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=confirm_reopen&token='.$newToken.
'">'.$langs->trans(
'ReOpen').
'</a>';
791 print
'<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans(
"NotEnoughPermissions").
'">'.$langs->trans(
'ReOpen').
'</a>';
800 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline',
'addproduceline',
'editline'))) {
801 print
'<form method="POST" action="'.$_SERVER[
"PHP_SELF"].
'">';
802 print
'<input type="hidden" name="token" value="'.newToken().
'">';
803 print
'<input type="hidden" name="action" value="confirm_'.$action.
'">';
804 print
'<input type="hidden" name="backtopage" value="'.$backtopage.
'">';
805 print
'<input type="hidden" name="id" value="'.$id.
'">';
808 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
809 $defaultstockmovementlabel =
GETPOST(
'inventorylabel',
'alphanohtml') ?
GETPOST(
'inventorylabel',
'alphanohtml') : $langs->trans(
"ProductionForRef",
$object->
ref);
812 print
'<div class="center'.(in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) ?
' formconsumeproduce' :
'').
'">';
813 print
'<div class="opacitymedium hideonsmartphone paddingbottom">'.$langs->trans(
"ConfirmProductionDesc", $langs->transnoentitiesnoconv(
"Confirm")).
'<br></div>';
814 print
'<span class="fieldrequired">'.$langs->trans(
"InventoryCode").
':</span> <input type="text" class="minwidth150 maxwidth200" name="inventorycode" value="'.$defaultstockmovementcode.
'"> ';
815 print
'<span class="clearbothonsmartphone"></span>';
816 print $langs->trans(
"MovementLabel").
': <input type="text" class="minwidth300" name="inventorylabel" value="'.$defaultstockmovementlabel.
'"><br><br>';
817 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>';
818 print
'<input type="submit" class="button" value="'.$langs->trans(
"Confirm").
'" name="confirm">';
820 print
'<input class="button button-cancel" type="submit" value="'.$langs->trans(
"Cancel").
'" name="cancel">';
834 if (!empty(
$object->table_element_line)) {
841 $res = $bom->fetch(
$object->fk_bom);
843 $bom->calculateCosts();
844 $bomcost = $bom->unit_cost;
850 print
'<!-- Lines to consume -->'.
"\n";
851 print
'<div class="fichecenter">';
852 print
'<div class="fichehalfleft">';
853 print
'<div class="clearboth"></div>';
855 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addconsumeline&token='.
newToken();
856 $permissiontoaddaconsumeline = (
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED) ? 1 : -2;
857 $parameters = array(
'morecss' =>
'reposition');
859 if ($permissiontoaddaconsumeline == -2) {
860 $helpText = $langs->trans(
'MOIsClosed');
864 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
865 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewConsumeLines'), $helpText,
'fa fa-plus-circle size15x', $url,
'', $permissiontoaddaconsumeline, $parameters);
868 print
load_fiche_titre($langs->trans(
'Consumption'), $newcardbutton,
'', 0,
'',
'',
'');
870 print
'<div class="div-table-responsive-no-min">';
871 print
'<table class="noborder noshadow centpercent nobottom">';
873 print
'<!-- Line of title for products to consume -->'.
"\n";
874 print
'<tr class="liste_titre trheight5em">';
876 print
'<td>'.$langs->trans(
"Product").
'</td>';
878 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
883 print
'<td class="right">'.$langs->trans(
"UnitCost").
'</td>';
886 print
'<td class="right classfortooltip" title="'.$langs->trans(
"QtyAlreadyConsumed").
'">';
887 print $langs->trans(
"QtyAlreadyConsumedShort");
891 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
892 print $langs->trans(
"Warehouse");
893 if (isModEnabled(
'workstation')) {
894 print
' '.$langs->trans(
"or").
' '.$langs->trans(
"Workstation");
897 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
898 $listwarehouses = $tmpwarehouse->list_array(1);
899 if (count($listwarehouses) > 1) {
900 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, $langs->trans(
"ForceTo"), 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
901 } elseif (count($listwarehouses) == 1) {
902 print
'<br>'.$form->selectarray(
'fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0,
'', 0, 0, 0,
'',
'minwidth100 maxwidth200', 1);
908 if (isModEnabled(
'stock')) {
910 print
'<td align="right">';
911 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
912 print $langs->trans(
"Stock");
917 if (isModEnabled(
'productbatch')) {
919 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
920 print $langs->trans(
"Batch");
932 if (
$object->status == Mo::STATUS_DRAFT) {
937 if ($permissiontodelete) {
943 if ($action ==
'addconsumeline') {
944 print
'<!-- Add line to consume -->'.
"\n";
945 print
'<tr class="liste_titre">';
948 print $form->select_produits(0,
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth150');
951 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width40 right"></td>';
964 if (isModEnabled(
'stock')) {
967 if (isModEnabled(
'productbatch')) {
971 print
'<td colspan="'.$colspan.
'">';
972 print
'<input type="submit" class="button buttongen button-add" name="addconsumelinebutton" value="'.$langs->trans(
"Add").
'">';
973 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdconsumelinebutton" value="'.$langs->trans(
"Cancel").
'">';
978 if (
$object->status == Mo::STATUS_DRAFT) {
982 if ($permissiontodelete) {
988 if (is_object($objectline)) {
989 $extrafields->fetch_name_optionals_label(
$object->table_element_line);
990 $temps = $objectline->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
991 if (!empty($temps)) {
992 print
'<tr class="liste_titre"><td style="padding-top: 20px" colspan="9" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
1001 $bomcostupdated = 0;
1004 $nblinetoconsume = 0;
1005 foreach (
$object->lines as $line) {
1006 if ($line->role ==
'toconsume') {
1011 $nblinetoconsumecursor = 0;
1012 foreach (
$object->lines as $line) {
1013 if ($line->role ==
'toconsume') {
1014 $nblinetoconsumecursor++;
1016 $tmpproduct =
new Product($db);
1017 $tmpproduct->fetch($line->fk_product);
1018 $linecost =
price2num($tmpproduct->pmp,
'MT');
1022 $costprice =
price2num((!empty($tmpproduct->cost_price)) ? $tmpproduct->cost_price : $tmpproduct->pmp);
1023 if (empty($costprice)) {
1024 require_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.product.class.php';
1026 if ($productFournisseur->find_min_price_product_fournisseur($line->fk_product, $line->qty) > 0) {
1027 $costprice = $productFournisseur->fourn_unitprice;
1035 if ($useunit && $line->fk_unit > 0) {
1037 $qtyhourservice = 0;
1038 if (preg_match(
'/^(\d+)([a-z]+)$/', $tmpproduct->duration, $reg)) {
1041 $qtyhourforline = 0;
1042 if ($line->fk_unit) {
1047 if ($qtyhourservice && $qtyhourforline) {
1048 $linecost =
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MT');
1049 $bomcostupdated +=
price2num(($qtyhourforline / $qtyhourservice * $costprice) /
$object->qty,
'MU');
1052 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1056 $bomcostupdated +=
price2num(($line->qty * $costprice) /
$object->qty,
'MU');
1060 $bomcostupdated =
price2num($bomcostupdated,
'MU');
1061 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1062 $alreadyconsumed = 0;
1063 foreach ($arrayoflines as $line2) {
1064 $alreadyconsumed += $line2[
'qty'];
1067 if ($action ==
'editline' && $lineid == $line->id) {
1068 $linecost =
price2num($tmpproduct->pmp,
'MT');
1070 $arrayoflines =
$object->fetchLinesLinked(
'consumed', $line->id);
1071 $alreadyconsumed = 0;
1072 if (is_array($arrayoflines) && !empty($arrayoflines)) {
1073 foreach ($arrayoflines as $line2) {
1074 $alreadyconsumed += $line2[
'qty'];
1077 $suffix =
'_' . $line->id;
1078 print
'<!-- Line to dispatch ' . $suffix .
' (line edited) -->' .
"\n";
1080 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1082 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1084 print
'<input name="lineid" type="hidden" value="' . $line->id .
'">';
1087 print
'<td>' . $tmpproduct->getNomUrl(1);
1088 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</span>';
1092 print
'<td class="right nowraponall">';
1093 print
'<input class="width40 right" name="qty_lineProduce" value="'. $line->qty.
'">';
1097 print
'<td class="right nowraponall">';
1105 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1110 print
'<td class="right">';
1111 print
' ' .
price2num($alreadyconsumed,
'MS');
1117 print $formproduct->selectWarehouses($line->fk_warehouse,
'warehouse_lineProduce',
'warehouseopen', 1);
1118 } elseif (isModEnabled(
'workstation')) {
1119 print $formproduct->selectWorkstations($line->fk_default_workstation,
'workstation_lineProduce', 1);
1124 if (isModEnabled(
'stock')) {
1125 print
'<td class="nowraponall right">';
1126 if ($tmpproduct->isStockManaged()) {
1127 if ($tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1128 print
img_warning($langs->trans(
'StockTooLow')).
' ';
1130 print
'<span class="left">'. $tmpproduct->stock_reel .
' </span>';
1136 if (isModEnabled(
'productbatch')) {
1140 print
'<td colspan="'.(3 + (
$object->status == Mo::STATUS_DRAFT ? 1 : 0) + ($permissiontodelete ? 1 : 0)).
'">';
1141 print
'<input type="submit" class="button buttongen button-add small nominwidth" name="save" value="' . $langs->trans(
"Save") .
'">';
1142 print
'<input type="submit" class="button buttongen button-cancel small nominwidth" name="cancel" value="' . $langs->trans(
"Cancel") .
'">';
1148 if (!empty($extrafields)) {
1149 $line->fetch_optionals();
1150 $temps = $line->showOptionals($extrafields,
'edit', array(),
'',
'', 1,
'line');
1151 if (!empty($temps)) {
1153 print
'<tr><td colspan="'.$colspan.
'"><div style="padding-top: 20px" id="extrafield_lines_area_edit" name="extrafield_lines_area_edit">';
1155 print
'</div></td></tr>';
1159 $suffix =
'_' . $line->id;
1160 print
'<!-- Line to dispatch ' . $suffix .
' -->' .
"\n";
1162 print
'<input id="qty_ordered' . $suffix .
'" type="hidden" value="' . $line->qty .
'">';
1163 print
'<input id="qty_dispatched' . $suffix .
'" type="hidden" value="' . $alreadyconsumed .
'">';
1165 print
'<tr data-line-id="' . $line->id .
'">';
1168 print
'<td>' . $tmpproduct->getNomUrl(1);
1169 print
'<br><div class="opacitymedium small tdoverflowmax150" title="' .
dol_escape_htmltag($tmpproduct->label) .
'">' . $tmpproduct->label .
'</div>';
1173 print
'<td class="right nowraponall">';
1175 if ($line->qty_frozen) {
1176 $help = ($help ?
'<br>' :
'') .
'<strong>' . $langs->trans(
"QuantityFrozen") .
'</strong>: ' .
yn(1) .
' (' . $langs->trans(
"QuantityConsumedInvariable") .
')';
1177 print $form->textwithpicto(
'', $help, -1,
'lock') .
' ';
1179 if ($line->disable_stock_change) {
1180 $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")) .
')';
1181 print $form->textwithpicto(
'', $help, -1,
'help') .
' ';
1187 print
'<td class="right nowraponall">';
1195 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1196 print
'<td class="right nowraponall">';
1197 print
price($linecost);
1202 print
'<td class="right">';
1203 if ($alreadyconsumed) {
1205 print
'jQuery(document).ready(function() {
1206 jQuery("#expandtoproduce' . $line->id .
'").click(function() {
1207 console.log("Expand mrp_production line ' . $line->id .
'");
1208 jQuery(".expanddetail' . $line->id .
'").toggle();';
1209 if ($nblinetoconsume == $nblinetoconsumecursor) {
1210 print
'if (jQuery("#tablelines").hasClass("nobottom")) { jQuery("#tablelines").removeClass("nobottom"); } else { jQuery("#tablelines").addClass("nobottom"); }';
1216 if (empty(
$conf->use_javascript_ajax)) {
1217 print
'<a href="' . $_SERVER[
"PHP_SELF"] .
'?collapse=' . $collapse .
',' . $line->id .
'">';
1219 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce' . $line->id .
'"');
1220 if (empty(
$conf->use_javascript_ajax)) {
1224 if ($nblinetoconsume == $nblinetoconsumecursor) {
1225 print
'<script>jQuery("#tablelines").removeClass("nobottom");</script>';
1228 print
' ' .
price2num($alreadyconsumed,
'MS');
1232 print
'<td class="tdoverflowmax100">';
1233 if ($tmpproduct->isStockManaged()) {
1235 if (
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') && $tmpwarehouse->id > 0) {
1236 print
img_picto(
'', $tmpwarehouse->picto) .
" " . $tmpwarehouse->label;
1238 if ($line->fk_warehouse > 0) {
1239 $warehouseline =
new Entrepot($db);
1240 $warehouseline->fetch($line->fk_warehouse);
1241 print $warehouseline->getNomUrl(1);
1245 if (isModEnabled(
'workstation') && $line->fk_default_workstation > 0) {
1247 $tmpworkstation->fetch($line->fk_default_workstation);
1248 print $tmpworkstation->getNomUrl(1);
1253 if (isModEnabled(
'stock')) {
1254 print
'<td class="nowraponall right">';
1256 if (!$line->disable_stock_change && $tmpproduct->stock_reel < ($line->qty - $alreadyconsumed)) {
1257 print
img_warning($langs->trans(
'StockTooLow')) .
' ';
1259 if (!
getDolGlobalString(
'STOCK_CONSUMPTION_FROM_MANUFACTURING_WAREHOUSE') || empty($tmpwarehouse->id)) {
1260 print
price2num($tmpproduct->stock_reel,
'MS');
1263 $tmpproduct->load_stock();
1264 $wh_stock = $tmpproduct->stock_warehouse[$tmpwarehouse->id];
1265 if (!empty($wh_stock)) {
1276 if (isModEnabled(
'productbatch')) {
1287 if (
$object->status == Mo::STATUS_DRAFT) {
1288 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1289 print
'<td class="center">';
1290 print
'<a class="reposition editfielda" href="' . $href .
'">';
1291 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1297 if ($permissiontodelete && empty($arrayoflines)) {
1298 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=deleteline&token=' .
newToken() .
'&lineid=' . ((int) $line->id);
1299 print
'<td class="center">';
1300 print
'<a class="reposition" href="' . $href .
'">';
1301 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1309 if (!empty($extrafields)) {
1310 $line->fetch_optionals();
1311 $temps = $line->showOptionals($extrafields,
'view', array(),
'',
'', 1,
'line');
1312 if (!empty($temps)) {
1314 print
'<tr><td colspan="'.$colspan.
'"><div id="extrafield_lines_area_'.$line->id.
'" name="extrafield_lines_area_'.$line->id.
'">';
1316 print
'</div></td></tr>';
1322 foreach ($arrayoflines as $line2) {
1323 print
'<tr class="expanddetail'.$line->id.
' hideobject opacitylow">';
1327 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1328 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1339 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1344 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1347 print
'<td class="tdoverflowmax150">';
1348 if ($line2[
'fk_warehouse'] > 0) {
1349 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1351 print $tmpwarehouse->getNomUrl(1);
1357 if (isModEnabled(
'stock')) {
1362 if (isModEnabled(
'productbatch')) {
1364 if ($line2[
'batch'] !=
'') {
1365 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1366 print $tmpbatch->getNomUrl(1);
1378 if (
$object->status == Mo::STATUS_DRAFT) {
1379 $href = $_SERVER[
"PHP_SELF"] .
'?id=' . ((int)
$object->id) .
'&action=editline&token=' .
newToken() .
'&lineid=' . ((int) $line2[
'rowid']);
1380 print
'<td class="center">';
1381 print
'<a class="reposition" href="' . $href .
'">';
1382 print
img_picto($langs->trans(
'TooltipEditAndRevertStockMovement'),
'edit');
1388 if ($permissiontodelete) {
1389 $href = $_SERVER[
"PHP_SELF"].
'?id='.((int)
$object->id).
'&action=deleteline&token='.
newToken().
'&lineid='.((int) $line2[
'rowid']).
'&fk_movement='.((int) $line2[
'fk_stock_movement']);
1390 print
'<td class="center">';
1391 print
'<a class="reposition" href="'.$href.
'">';
1392 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
'delete');
1400 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1402 print
'<!-- Enter line to consume -->'.
"\n";
1404 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1406 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToConsume").
'</span></td>';
1407 $preselected = (GETPOSTISSET(
'qty-'.$line->id.
'-'.$i) ?
GETPOST(
'qty-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyconsumed));
1408 if ($action ==
'consumeorproduce' && !
getDolGlobalString(
'MRP_AUTO_SET_REMAINING_QUANTITIES_TO_BE_CONSUMED') && !GETPOSTISSET(
'qty-'.$line->id.
'-'.$i)) {
1413 if (
getDolGlobalString(
'MRP_NEVER_CONSUME_MORE_THAN_EXPECTED') && ($line->qty - $alreadyconsumed) <= 0) {
1414 $disable =
'disabled';
1418 print
'<input type="hidden" name="product-'.$line->id.
'-'.$i.
'" value="'.$line->fk_product.
'">';
1421 print
'<td class="right"><input type="text" class="width50 right" id="qtytoconsume-' . $line->id .
'-' . $i .
'" name="qty-' . $line->id .
'-' . $i .
'" value="' . $preselected .
'" ' . $disable .
'></td>';
1427 if ($permissiontoupdatecost &&
getDolGlobalString(
'MRP_SHOW_COST_FOR_CONSUMPTION')) {
1437 if (empty($line->disable_stock_change)) {
1438 $preselected = (GETPOSTISSET(
'idwarehouse-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehouse-'.$line->id.
'-'.$i) : ($tmpproduct->fk_default_warehouse > 0 ? $tmpproduct->fk_default_warehouse :
'ifone'));
1439 print $formproduct->selectWarehouses($preselected,
'idwarehouse-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0, array(),
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1441 print
'<span class="opacitymedium">'.$langs->trans(
"DisableStockChange").
'</span>';
1444 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1449 if (isModEnabled(
'stock')) {
1454 if (isModEnabled(
'productbatch')) {
1455 print
'<td class="nowraponall">';
1456 if ($tmpproduct->status_batch) {
1457 $preselected = (GETPOSTISSET(
'batch-'.$line->id.
'-'.$i) ?
GETPOST(
'batch-'.$line->id.
'-'.$i) :
'');
1458 print
'<input type="text" class="width75" name="batch-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'" list="batch-'.$line->id.
'-'.$i.
'">';
1459 print $formproduct->selectLotDataList(
'batch-'.$line->id.
'-'.$i, 0, $line->fk_product, 0, array());
1466 print
'<td align="right" class="split">';
1467 print
' '.img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.((int) $line->id).
', \''.
dol_escape_js($type).
'\', \
'qtymissingconsume\')"');
1471 print
'<td align="right" class="splitall">';
1472 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1473 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" data-max-qty="1" onClick="addDispatchLine('.$line->id.
', \'batch\', \'allmissingconsume\')"');
1478 if (
$object->status == Mo::STATUS_DRAFT) {
1483 if ($permissiontodelete) {
1497 print
'<script type="text/javascript">
1498 $(document).ready(function () {
1499 $("select[name=fk_default_warehouse]").change(function() {
1500 var fk_default_warehouse = $("option:selected", this).val();
1501 $("select[name^=idwarehouse-]").val(fk_default_warehouse).change();
1506 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall')) &&
1508 print
'<script>$(document).ready(function () {
1509 $("#fk_default_warehouse").change();
1517 print
'<div class="fichehalfright">';
1518 print
'<div class="clearboth"></div>';
1520 $nblinetoproduce = 0;
1521 foreach (
$object->lines as $line) {
1522 if ($line->role ==
'toproduce') {
1527 $newcardbutton =
'';
1528 $url = $_SERVER[
"PHP_SELF"].
'?id='.
$object->id.
'&action=addproduceline&token='.
newToken();
1529 $permissiontoaddaproductline =
$object->status != $object::STATUS_PRODUCED &&
$object->status != $object::STATUS_CANCELED;
1530 $parameters = array(
'morecss' =>
'reposition');
1531 if ($action !=
'consumeorproduce' && $action !=
'consumeandproduceall') {
1532 if ($nblinetoproduce == 0 ||
$object->mrptype == 1) {
1533 $newcardbutton =
dolGetButtonTitle($langs->trans(
'AddNewProduceLines'),
'',
'fa fa-plus-circle size15x', $url,
'', (
int) $permissiontoaddaproductline, $parameters);
1537 print
load_fiche_titre($langs->trans(
'Production'), $newcardbutton,
'', 0,
'',
'');
1539 print
'<div class="div-table-responsive-no-min">';
1540 print
'<table id="tablelinestoproduce" class="noborder noshadow nobottom centpercent">';
1542 print
'<tr class="liste_titre trheight5em">';
1544 print
'<td>'.$langs->trans(
"Product").
'</td>';
1546 print
'<td class="right">'.$langs->trans(
"Qty").
'</td>';
1549 print
'<td class="right">'.$langs->trans(
"Unit").
'</td>';
1552 if ($permissiontoupdatecost) {
1553 if (empty($bomcostupdated)) {
1554 print
'<td class="right classfortooltip" title="'.$langs->trans(
"AmountUsedToUpdateWAP").
'">';
1555 print $langs->trans(
"UnitCost");
1558 print
'<td class="right classfortooltip" title="'.$langs->trans(
"AmountUsedToUpdateWAP").
'">';
1559 print $langs->trans(
"ManufacturingPrice");
1564 print
'<td class="right classfortooltip" title="'.$langs->trans(
"QtyAlreadyProduced").
'">';
1565 print $langs->trans(
"QtyAlreadyProducedShort");
1569 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1570 print $langs->trans(
"Warehouse");
1575 if (isModEnabled(
'productbatch')) {
1577 if ($collapse || in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1578 print $langs->trans(
"Batch");
1590 if ($permissiontodelete) {
1596 if ($action ==
'addproduceline') {
1597 print
'<!-- Add line to produce -->'.
"\n";
1598 print
'<tr class="liste_titre">';
1602 print $form->select_produits(0,
'productidtoadd',
'', 0, 0, -1, 2,
'', 1, array(), 0,
'1', 0,
'maxwidth300');
1605 print
'<td class="right"><input type="text" name="qtytoadd" value="1" class="width50 right"></td>';
1611 if ($permissiontoupdatecost) {
1615 print
'<td colspan="2">';
1616 print
'<input type="submit" class="button buttongen button-add" name="addproducelinebutton" value="'.$langs->trans(
"Add").
'">';
1617 print
'<input type="submit" class="button buttongen button-cancel" name="canceladdproducelinebutton" value="'.$langs->trans(
"Cancel").
'">';
1620 if (isModEnabled(
'productbatch')) {
1630 if ($permissiontodelete) {
1637 $nblinetoproduce = 0;
1638 foreach (
$object->lines as $line) {
1639 if ($line->role ==
'toproduce') {
1644 $nblinetoproducecursor = 0;
1645 foreach (
$object->lines as $line) {
1646 if ($line->role ==
'toproduce') {
1649 $nblinetoproducecursor++;
1651 $tmpproduct =
new Product($db);
1652 $tmpproduct->fetch($line->fk_product);
1654 $arrayoflines =
$object->fetchLinesLinked(
'produced', $line->id);
1655 $alreadyproduced = 0;
1656 foreach ($arrayoflines as $line2) {
1657 $alreadyproduced += $line2[
'qty'];
1660 $suffix =
'_'.$line->id;
1661 print
'<!-- Line to dispatch '.$suffix.
' (toproduce) -->'.
"\n";
1663 print
'<input id="qty_ordered'.$suffix.
'" type="hidden" value="'.$line->qty.
'">';
1664 print
'<input id="qty_dispatched'.$suffix.
'" type="hidden" value="'.$alreadyproduced.
'">';
1668 print
'<td>'.$tmpproduct->getNomUrl(1);
1669 print
'<br><span class="opacitymedium small">'.$tmpproduct->label.
'</span>';
1672 print
'<td class="right">'.$line->qty.
'</td>';
1675 print
'<td class="right">'.measuringUnitString($line->fk_unit,
'',
'', 1).
'</td>';
1678 if ($permissiontoupdatecost) {
1680 $manufacturingcost = 0;
1681 $manufacturingcostsrc =
'';
1683 $manufacturingcost = $bomcostupdated;
1684 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1685 if (empty($manufacturingcost)) {
1686 $manufacturingcost = $bomcost;
1687 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1689 if (empty($manufacturingcost)) {
1690 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1691 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1693 if (empty($manufacturingcost)) {
1694 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1695 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1699 print
'<td class="right nowraponall" title="'.dol_escape_htmltag($manufacturingcostsrc).
'">';
1700 if ($manufacturingcost) {
1701 print
price($manufacturingcost);
1706 print
'<td class="right nowraponall">';
1707 if ($alreadyproduced) {
1709 print
'jQuery(document).ready(function() {
1710 jQuery("#expandtoproduce'.$line->id.
'").click(function() {
1711 console.log("Expand mrp_production line '.$line->id.
'");
1712 jQuery(".expanddetailtoproduce'.$line->id.
'").toggle();';
1713 if ($nblinetoproduce == $nblinetoproducecursor) {
1714 print
'if (jQuery("#tablelinestoproduce").hasClass("nobottom")) { jQuery("#tablelinestoproduce").removeClass("nobottom"); } else { jQuery("#tablelinestoproduce").addClass("nobottom"); }';
1720 if (empty(
$conf->use_javascript_ajax)) {
1721 print
'<a href="'.$_SERVER[
"PHP_SELF"].
'?collapse='.$collapse.
','.$line->id.
'">';
1723 print
img_picto($langs->trans(
"ShowDetails"),
"chevron-down",
'id="expandtoproduce'.$line->id.
'"');
1724 if (empty(
$conf->use_javascript_ajax)) {
1728 print
' '.$alreadyproduced;
1734 if (isModEnabled(
'productbatch')) {
1744 if ($permissiontodelete) {
1745 if ($line->origin_type ==
'free') {
1746 $href = $_SERVER[
"PHP_SELF"];
1747 $href .=
'?id='.$object->id;
1748 $href .=
'&action=deleteline';
1749 $href .=
'&token='.newToken();
1750 $href .=
'&lineid='.$line->id;
1751 print
'<td class="center">';
1752 print
'<a class="reposition" href="'.$href.
'">';
1753 print
img_picto($langs->trans(
'TooltipDeleteAndRevertStockMovement'),
"delete");
1763 foreach ($arrayoflines as $line2) {
1764 print
'<tr class="expanddetailtoproduce'.$line->id.
' hideobject opacitylow">';
1767 $tmpstockmovement->id = $line2[
'fk_stock_movement'];
1768 print
'<a href="'.DOL_URL_ROOT.
'/product/stock/movement_list.php?search_ref='.$tmpstockmovement->id.
'">'.
img_picto($langs->trans(
"StockMovement"),
'movement',
'class="paddingright"').
'</a>';
1778 if ($permissiontoupdatecost) {
1782 print
'<td class="right">'.$line2[
'qty'].
'</td>';
1784 print
'<td class="tdoverflowmax150">';
1785 if ($line2[
'fk_warehouse'] > 0) {
1786 $result = $tmpwarehouse->fetch($line2[
'fk_warehouse']);
1788 print $tmpwarehouse->getNomUrl(1);
1793 if (isModEnabled(
'productbatch')) {
1795 if ($line2[
'batch'] !=
'') {
1796 $tmpbatch->fetch(0, $line2[
'fk_product'], $line2[
'batch']);
1797 print $tmpbatch->getNomUrl(1);
1808 if ($permissiontodelete) {
1814 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall'))) {
1815 print
'<!-- Enter line to produce -->'.
"\n";
1817 print
'<tr data-max-qty="'.$maxQty.
'" name="batch_'.$line->id.
'_'.$i.
'">';
1819 print
'<td><span class="opacitymedium">'.$langs->trans(
"ToProduce").
'</span></td>';
1820 $preselected = (GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'qtytoproduce-'.$line->id.
'-'.$i) : max(0, $line->qty - $alreadyproduced));
1821 if ($action ==
'consumeorproduce' && !GETPOSTISSET(
'qtytoproduce-'.$line->id.
'-'.$i)) {
1825 print
'<td class="right"><input type="text" class="width50 right" id="qtytoproduce-'.$line->id.
'-'.$i.
'" name="qtytoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1828 print
'<td class="right"></td>';
1831 if ($permissiontoupdatecost) {
1833 $manufacturingcost = 0;
1834 $manufacturingcostsrc =
'';
1836 $manufacturingcost = $bomcostupdated;
1837 $manufacturingcostsrc = $langs->trans(
"CalculatedFromProductsToConsume");
1838 if (empty($manufacturingcost)) {
1839 $manufacturingcost = $bomcost;
1840 $manufacturingcostsrc = $langs->trans(
"ValueFromBom");
1842 if (empty($manufacturingcost)) {
1843 $manufacturingcost =
price2num($tmpproduct->cost_price,
'MU');
1844 $manufacturingcostsrc = $langs->trans(
"CostPrice");
1846 if (empty($manufacturingcost)) {
1847 $manufacturingcost =
price2num($tmpproduct->pmp,
'MU');
1848 $manufacturingcostsrc = $langs->trans(
"PMPValue");
1853 $preselected = (GETPOSTISSET(
'pricetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'pricetoproduce-'.$line->id.
'-'.$i) : ($manufacturingcost ?
price($manufacturingcost) :
''));
1854 print
'<td class="right"><input type="text" class="width75 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'"></td>';
1856 print
'<td><input type="hidden" class="width50 right" name="pricetoproduce-'.$line->id.
'-'.$i.
'" value="'.($manufacturingcost ? $manufacturingcost :
'').
'"></td>';
1864 $preselected = (GETPOSTISSET(
'idwarehousetoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'idwarehousetoproduce-'.$line->id.
'-'.$i) : (
$object->fk_warehouse > 0 ?
$object->fk_warehouse :
'ifone'));
1865 print $formproduct->selectWarehouses($preselected,
'idwarehousetoproduce-'.$line->id.
'-'.$i,
'', 1, 0, $line->fk_product,
'', 1, 0, array(),
'maxwidth200 csswarehouse_'.$line->id.
'_'.$i);
1867 print
'<span class="opacitymedium">'.$langs->trans(
"NoStockChangeOnServices").
'</span>';
1871 if (isModEnabled(
'productbatch')) {
1873 if ($tmpproduct->status_batch) {
1874 $preselected = (GETPOSTISSET(
'batchtoproduce-'.$line->id.
'-'.$i) ?
GETPOST(
'batchtoproduce-'.$line->id.
'-'.$i) :
'');
1875 print
'<input type="text" class="width75" name="batchtoproduce-'.$line->id.
'-'.$i.
'" value="'.$preselected.
'">';
1879 if ($tmpproduct->status_batch) {
1881 print
'<td align="right" class="split">';
1882 print
img_picto($langs->trans(
'AddStockLocationLine'),
'split.png',
'class="splitbutton" onClick="addDispatchLine('.$line->id.
', \''.$type.
'\', \
'qtymissing\')"');
1885 print
'<td align="right" class="splitall">';
1886 if (($action ==
'consumeorproduce' || $action ==
'consumeandproduceall') && $tmpproduct->status_batch == 2) {
1887 print
img_picto($langs->trans(
'SplitAllQuantity'),
'split.png',
'class="splitbutton splitallbutton field-error-icon" onClick="addDispatchLine('.$line->id.
', \'batch\', \'alltoproduce\')"');
1913 if (in_array($action, array(
'consumeorproduce',
'consumeandproduceall',
'addconsumeline'))) {
1917 <script
type=
"text/javascript" language=
"javascript">
1919 $(document).ready(
function() {
1921 updateselectbatchbywarehouse();
1923 updateselectwarehousebybatch();
1926 function updateselectbatchbywarehouse() {
1927 $(document).on(
'change',
"select[name*='idwarehouse']",
function () {
1928 console.log(
"We change warehouse so we update the list of possible batch number");
1930 var selectwarehouse = $(
this);
1932 var selectbatch_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'batch');
1933 var selectbatch = $(
"datalist[id*='" + selectbatch_name +
"']");
1934 var selectedbatch = selectbatch.val();
1936 var product_element_name = selectwarehouse.attr(
'name').replace(
'idwarehouse',
'product');
1940 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
1942 action:
"updateselectbatchbywarehouse",
1943 permissiontoproduce: <?php echo $permissiontoproduce ?>,
1944 warehouse_id: $(
this).val(),
1945 token:
'<?php echo currentToken(); ?>',
1946 product_id: $(
"input[name='" + product_element_name +
"']").val()
1948 }).done(
function (data) {
1950 selectbatch.empty();
1952 if (typeof data ==
"object") {
1953 console.log(
"data is already type object, no need to parse it");
1955 console.log(
"data is type "+(typeof data));
1956 data = JSON.parse(data);
1959 selectbatch.append($(
'<option>', {
1963 $.each(data,
function (key, value) {
1965 if(selectwarehouse.val() == -1) {
1966 var label = key +
" (<?php echo $langs->trans('Stock total') ?> : " + value +
")";
1968 var label = key +
" (<?php echo $langs->trans('Stock') ?> : " + value +
")";
1971 if(key === selectedbatch) {
1972 var option =
'<option value="'+key+
'" selected>'+ label +
'</option>';
1974 var option =
'<option value="'+key+
'">'+ label +
'</option>';
1977 selectbatch.append(option);
1983 function updateselectwarehousebybatch() {
1984 $(document).on(
'change',
'input[name*=batch]',
function(){
1985 console.log(
"We change batch so we update the list of possible warehouses");
1987 var selectbatch = $(
this);
1989 var selectwarehouse_name = selectbatch.attr(
'name').replace(
'batch',
'idwarehouse');
1990 var selectwarehouse = $(
"select[name*='" + selectwarehouse_name +
"']");
1991 var selectedwarehouse = selectwarehouse.val();
1993 if(selectedwarehouse != -1){
1997 var product_element_name = selectbatch.attr(
'name').replace(
'batch',
'product');
2001 url:
"<?php echo DOL_URL_ROOT . '/mrp/ajax/interface.php'; ?>",
2003 action:
"updateselectwarehousebybatch",
2004 permissiontoproduce: <?php echo $permissiontoproduce ?>,
2005 batch: $(
this).val(),
2006 token:
'<?php echo currentToken(); ?>',
2007 product_id: $(
"input[name='" + product_element_name +
"']").val()
2009 }).done(
function (data) {
2011 if (typeof data ==
"object") {
2012 console.log(
"data is already type object, no need to parse it");
2014 console.log(
"data is type "+(typeof data));
2015 data = JSON.parse(data);
2019 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_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
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.