1<?php 2/* Copyright (C) 2017-2020 Laurent Destailleur <eldy@users.sourceforge.net> 3 * Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 */ 18 19/** 20 * \file htdocs/bom/bom_card.php 21 * \ingroup bom 22 * \brief Page to create/edit/view bom 23 */ 24 25// Load Dolibarr environment 26require '../main.inc.php'; 27require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; 28require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; 29require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php'; 30require_once DOL_DOCUMENT_ROOT.'/bom/lib/bom.lib.php'; 31 32// Load translation files required by the page 33$langs->loadLangs(array("mrp", "other")); 34 35// Get parameters 36$id = GETPOST('id', 'int'); 37$ref = GETPOST('ref', 'alpha'); 38$action = GETPOST('action', 'aZ09'); 39$confirm = GETPOST('confirm', 'alpha'); 40$cancel = GETPOST('cancel', 'aZ09'); 41$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'bomcard'; // To manage different context of search 42$backtopage = GETPOST('backtopage', 'alpha'); 43$lineid = GETPOST('lineid', 'int'); 44 45// PDF 46$hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0)); 47$hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0)); 48$hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0)); 49 50// Initialize technical objects 51$object = new BOM($db); 52$extrafields = new ExtraFields($db); 53$diroutputmassaction = $conf->bom->dir_output.'/temp/massgeneration/'.$user->id; 54$hookmanager->initHooks(array('bomcard', 'globalcard')); // Note that conf->hooks_modules contains array 55// Fetch optionals attributes and labels 56$extrafields->fetch_name_optionals_label($object->table_element); 57$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); 58 59// Initialize array of search criterias 60$search_all = GETPOST("search_all", 'alpha'); 61$search = array(); 62foreach ($object->fields as $key => $val) 63{ 64 if (GETPOST('search_'.$key, 'alpha')) $search[$key] = GETPOST('search_'.$key, 'alpha'); 65} 66 67if (empty($action) && empty($id) && empty($ref)) $action = 'view'; 68 69// Load object 70include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. 71 72// Security check - Protection if external user 73//if ($user->socid > 0) accessforbidden(); 74//if ($user->socid > 0) $socid = $user->socid; 75//$isdraft = (($object->statut == $object::STATUS_DRAFT) ? 1 : 0); 76//$result = restrictedArea($user, 'bom', $object->id, '', '', 'fk_soc', 'rowid', $isdraft); 77 78$permissionnote = $user->rights->bom->write; // Used by the include of actions_setnotes.inc.php 79$permissiondellink = $user->rights->bom->write; // Used by the include of actions_dellink.inc.php 80$permissiontoadd = $user->rights->bom->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php 81$permissiontodelete = $user->rights->bom->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); 82$upload_dir = $conf->bom->multidir_output[isset($object->entity) ? $object->entity : 1]; 83 84 85/* 86 * Actions 87 */ 88 89$parameters = array(); 90$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks 91if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 92 93if (empty($reshook)) 94{ 95 $error = 0; 96 97 $backurlforlist = DOL_URL_ROOT.'/bom/bom_list.php'; 98 99 if (empty($backtopage) || ($cancel && empty($id))) { 100 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { 101 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) $backtopage = $backurlforlist; 102 else $backtopage = dol_buildpath('/bom/bom_card.php', 1).'?id='.($id > 0 ? $id : '__ID__'); 103 } 104 } 105 106 $triggermodname = 'BOM_MODIFY'; // Name of trigger action code to execute when we modify record 107 108 // Actions cancel, add, update, delete or clone 109 include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php'; 110 111 // Actions when linking object each other 112 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; 113 114 // Actions when printing a doc from card 115 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; 116 117 // Action to move up and down lines of object 118 //include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; 119 120 // Action to build doc 121 include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; 122 123 // Actions to send emails 124 $triggersendname = 'BOM_SENTBYMAIL'; 125 $autocopy = 'MAIN_MAIL_AUTOCOPY_BOM_TO'; 126 $trackid = 'bom'.$object->id; 127 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; 128 129 // Add line 130 if ($action == 'addline' && $user->rights->bom->write) 131 { 132 $langs->load('errors'); 133 $error = 0; 134 135 // Set if we used free entry or predefined product 136 $idprod = (int) GETPOST('idprod', 'int'); 137 $qty = price2num(GETPOST('qty', 'alpha'), 'MS'); 138 $qty_frozen = price2num(GETPOST('qty_frozen', 'alpha'), 'MS'); 139 $disable_stock_change = GETPOST('disable_stock_change', 'int'); 140 $efficiency = price2num(GETPOST('efficiency', 'alpha')); 141 142 if ($qty == '') { 143 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors'); 144 $error++; 145 } 146 if (!($idprod > 0)) { 147 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Product')), null, 'errors'); 148 $error++; 149 } 150 151 if ($object->fk_product == $idprod) { 152 setEventMessages($langs->trans('TheProductXIsAlreadyTheProductToProduce'), null, 'errors'); 153 $error++; 154 } 155 156 if (!$error) 157 { 158 $bomline = new BOMLine($db); 159 $bomline->fk_bom = $id; 160 $bomline->fk_product = $idprod; 161 $bomline->qty = $qty; 162 $bomline->qty_frozen = (int) $qty_frozen; 163 $bomline->disable_stock_change = (int) $disable_stock_change; 164 $bomline->efficiency = $efficiency; 165 166 // Rang to use 167 $rangmax = $object->line_max(0); 168 $ranktouse = $rangmax + 1; 169 170 $bomline->position = ($ranktouse + 1); 171 172 $result = $bomline->create($user); 173 if ($result <= 0) { 174 setEventMessages($bomline->error, $bomline->errors, 'errors'); 175 $action = ''; 176 } else { 177 unset($_POST['idprod']); 178 unset($_POST['qty']); 179 unset($_POST['qty_frozen']); 180 unset($_POST['disable_stock_change']); 181 182 $object->fetchLines(); 183 184 $object->calculateCosts(); 185 } 186 } 187 } 188 189 // Add line 190 if ($action == 'updateline' && $user->rights->bom->write) 191 { 192 $langs->load('errors'); 193 $error = 0; 194 195 // Set if we used free entry or predefined product 196 $qty = price2num(GETPOST('qty', 'alpha'), 'MS'); 197 $qty_frozen = price2num(GETPOST('qty_frozen', 'alpha'), 'MS'); 198 $disable_stock_change = GETPOST('disable_stock_change', 'int'); 199 $efficiency = price2num(GETPOST('efficiency', 'alpha')); 200 201 if ($qty == '') { 202 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors'); 203 $error++; 204 } 205 206 $bomline = new BOMLine($db); 207 $bomline->fetch($lineid); 208 $bomline->qty = $qty; 209 $bomline->qty_frozen = (int) $qty_frozen; 210 $bomline->disable_stock_change = (int) $disable_stock_change; 211 $bomline->efficiency = $efficiency; 212 213 $result = $bomline->update($user); 214 if ($result <= 0) 215 { 216 setEventMessages($bomline->error, $bomline->errors, 'errors'); 217 $action = ''; 218 } else { 219 unset($_POST['idprod']); 220 unset($_POST['qty']); 221 unset($_POST['qty_frozen']); 222 unset($_POST['disable_stock_change']); 223 224 $object->fetchLines(); 225 226 $object->calculateCosts(); 227 } 228 } 229} 230 231 232/* 233 * View 234 */ 235 236$form = new Form($db); 237$formfile = new FormFile($db); 238 239llxHeader('', $langs->trans("BOM"), ''); 240 241// Example : Adding jquery code 242print '<script type="text/javascript" language="javascript"> 243jQuery(document).ready(function() { 244 function init_myfunc() 245 { 246 jQuery("#myid").removeAttr(\'disabled\'); 247 jQuery("#myid").attr(\'disabled\',\'disabled\'); 248 } 249 init_myfunc(); 250 jQuery("#mybutton").click(function() { 251 init_myfunc(); 252 }); 253}); 254</script>'; 255 256 257// Part to create 258if ($action == 'create') 259{ 260 print load_fiche_titre($langs->trans("NewBOM"), '', 'bom'); 261 262 print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">'; 263 print '<input type="hidden" name="token" value="'.newToken().'">'; 264 print '<input type="hidden" name="action" value="add">'; 265 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">'; 266 267 print dol_get_fiche_head(array(), ''); 268 269 print '<table class="border centpercent tableforfieldcreate">'."\n"; 270 271 // Common attributes 272 include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_add.tpl.php'; 273 274 // Other attributes 275 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; 276 277 print '</table>'."\n"; 278 279 print dol_get_fiche_end(); 280 281 print '<div class="center">'; 282 print '<input type="submit" class="button" name="add" value="'.dol_escape_htmltag($langs->trans("Create")).'">'; 283 print ' '; 284 print '<input type="'.($backtopage ? "submit" : "button").'" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'"'.($backtopage ? '' : ' onclick="javascript:history.go(-1)"').'>'; // Cancel for create does not post form if we don't know the backtopage 285 print '</div>'; 286 287 print '</form>'; 288} 289 290// Part to edit record 291if (($id || $ref) && $action == 'edit') 292{ 293 print load_fiche_titre($langs->trans("BillOfMaterials"), '', 'cubes'); 294 295 print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">'; 296 print '<input type="hidden" name="token" value="'.newToken().'">'; 297 print '<input type="hidden" name="action" value="update">'; 298 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">'; 299 print '<input type="hidden" name="id" value="'.$object->id.'">'; 300 301 print dol_get_fiche_head(); 302 303 //$object->fields['keyfield']['disabled'] = 1; 304 305 print '<table class="border centpercent tableforfieldedit">'."\n"; 306 307 // Common attributes 308 include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_edit.tpl.php'; 309 310 // Other attributes 311 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php'; 312 313 print '</table>'; 314 315 print dol_get_fiche_end(); 316 317 print '<div class="center"><input type="submit" class="button button-save" name="save" value="'.$langs->trans("Save").'">'; 318 print ' <input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">'; 319 print '</div>'; 320 321 print '</form>'; 322} 323 324// Part to show record 325if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) 326{ 327 $res = $object->fetch_optionals(); 328 329 $head = bomPrepareHead($object); 330 print dol_get_fiche_head($head, 'card', $langs->trans("BillOfMaterials"), -1, 'bom'); 331 332 $formconfirm = ''; 333 334 // Confirmation to delete 335 if ($action == 'delete') 336 { 337 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteBillOfMaterials'), $langs->trans('ConfirmDeleteBillOfMaterials'), 'confirm_delete', '', 0, 1); 338 } 339 // Confirmation to delete line 340 if ($action == 'deleteline') 341 { 342 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); 343 } 344 345 // Confirmation of validation 346 if ($action == 'validate') 347 { 348 // We check that object has a temporary ref 349 $ref = substr($object->ref, 1, 4); 350 if ($ref == 'PROV') { 351 $object->fetch_product(); 352 $numref = $object->getNextNumRef($object->product); 353 } else { 354 $numref = $object->ref; 355 } 356 357 $text = $langs->trans('ConfirmValidateBom', $numref); 358 /*if (! empty($conf->notification->enabled)) 359 { 360 require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; 361 $notify = new Notify($db); 362 $text .= '<br>'; 363 $text .= $notify->confirmMessage('BOM_VALIDATE', $object->socid, $object); 364 }*/ 365 366 $formquestion = array(); 367 if (!empty($conf->bom->enabled)) 368 { 369 $langs->load("mrp"); 370 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; 371 $formproduct = new FormProduct($db); 372 $forcecombo = 0; 373 if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy 374 $formquestion = array( 375 // 'text' => $langs->trans("ConfirmClone"), 376 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), 377 // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), 378 ); 379 } 380 381 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('Validate'), $text, 'confirm_validate', $formquestion, 0, 1, 220); 382 } 383 384 // Confirmation of closing 385 if ($action == 'close') 386 { 387 $text = $langs->trans('ConfirmCloseBom', $object->ref); 388 /*if (! empty($conf->notification->enabled)) 389 { 390 require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; 391 $notify = new Notify($db); 392 $text .= '<br>'; 393 $text .= $notify->confirmMessage('BOM_CLOSE', $object->socid, $object); 394 }*/ 395 396 $formquestion = array(); 397 if (!empty($conf->bom->enabled)) 398 { 399 $langs->load("mrp"); 400 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; 401 $formproduct = new FormProduct($db); 402 $forcecombo = 0; 403 if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy 404 $formquestion = array( 405 // 'text' => $langs->trans("ConfirmClone"), 406 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), 407 // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), 408 ); 409 } 410 411 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('Close'), $text, 'confirm_close', $formquestion, 0, 1, 220); 412 } 413 414 // Confirmation of reopen 415 if ($action == 'reopen') 416 { 417 $text = $langs->trans('ConfirmReopenBom', $object->ref); 418 /*if (! empty($conf->notification->enabled)) 419 { 420 require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; 421 $notify = new Notify($db); 422 $text .= '<br>'; 423 $text .= $notify->confirmMessage('BOM_CLOSE', $object->socid, $object); 424 }*/ 425 426 $formquestion = array(); 427 if (!empty($conf->bom->enabled)) 428 { 429 $langs->load("mrp"); 430 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; 431 $formproduct = new FormProduct($db); 432 $forcecombo = 0; 433 if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy 434 $formquestion = array( 435 // 'text' => $langs->trans("ConfirmClone"), 436 // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), 437 // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), 438 ); 439 } 440 441 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ReOpen'), $text, 'confirm_reopen', $formquestion, 0, 1, 220); 442 } 443 444 // Clone confirmation 445 if ($action == 'clone') { 446 // Create an array for form 447 $formquestion = array(); 448 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneBillOfMaterials', $object->ref), 'confirm_clone', $formquestion, 'yes', 1); 449 } 450 451 // Confirmation of action xxxx 452 if ($action == 'setdraft') 453 { 454 $text = $langs->trans('ConfirmSetToDraft', $object->ref); 455 456 $formquestion = array(); 457 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('SetToDraft'), $text, 'confirm_setdraft', $formquestion, 0, 1, 220); 458 } 459 460 // Call Hook formConfirm 461 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid); 462 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook 463 if (empty($reshook)) $formconfirm .= $hookmanager->resPrint; 464 elseif ($reshook > 0) $formconfirm = $hookmanager->resPrint; 465 466 // Print form confirm 467 print $formconfirm; 468 469 470 // Object card 471 // ------------------------------------------------------------ 472 $linkback = '<a href="'.dol_buildpath('/bom/bom_list.php', 1).'?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>'; 473 474 $morehtmlref = '<div class="refidno">'; 475 /* 476 // Ref bis 477 $morehtmlref.=$form->editfieldkey("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->bom->creer, 'string', '', 0, 1); 478 $morehtmlref.=$form->editfieldval("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->bom->creer, 'string', '', null, null, '', 1); 479 // Thirdparty 480 $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1); 481 // Project 482 if (! empty($conf->projet->enabled)) 483 { 484 $langs->load("projects"); 485 $morehtmlref.='<br>'.$langs->trans('Project') . ' '; 486 if ($permissiontoadd) 487 { 488 if ($action != 'classify') 489 $morehtmlref.='<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : '; 490 if ($action == 'classify') { 491 //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); 492 $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">'; 493 $morehtmlref.='<input type="hidden" name="action" value="classin">'; 494 $morehtmlref.='<input type="hidden" name="token" value="'.newToken().'">'; 495 $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1); 496 $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">'; 497 $morehtmlref.='</form>'; 498 } else { 499 $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); 500 } 501 } else { 502 if (! empty($object->fk_project)) { 503 $proj = new Project($db); 504 $proj->fetch($object->fk_project); 505 $morehtmlref.=$proj->getNomUrl(); 506 } else { 507 $morehtmlref.=''; 508 } 509 } 510 } 511 */ 512 $morehtmlref .= '</div>'; 513 514 515 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); 516 517 518 print '<div class="fichecenter">'; 519 print '<div class="fichehalfleft">'; 520 print '<div class="underbanner clearboth"></div>'; 521 print '<table class="border centpercent tableforfield">'."\n"; 522 523 // Common attributes 524 $keyforbreak = 'duration'; 525 include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php'; 526 527 print '<tr><td>'.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).'</td><td>'.price($object->total_cost).'</td></tr>'; 528 print '<tr><td>'.$langs->trans("UnitCost").'</td><td>'.price($object->unit_cost).'</td></tr>'; 529 530 // Other attributes 531 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; 532 533 print '</table>'; 534 print '</div>'; 535 print '</div>'; 536 537 print '<div class="clearboth"></div>'; 538 539 print dol_get_fiche_end(); 540 541 542 543 /* 544 * Lines 545 */ 546 547 if (!empty($object->table_element_line)) 548 { 549 print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '#addline' : '').'" method="POST"> 550 <input type="hidden" name="token" value="' . newToken().'"> 551 <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'"> 552 <input type="hidden" name="mode" value=""> 553 <input type="hidden" name="id" value="' . $object->id.'"> 554 '; 555 556 if (!empty($conf->use_javascript_ajax) && $object->status == 0) { 557 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php'; 558 } 559 560 print '<div class="div-table-responsive-no-min">'; 561 if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) 562 { 563 print '<table id="tablelines" class="noborder noshadow" width="100%">'; 564 } 565 566 if (!empty($object->lines)) 567 { 568 $object->printObjectLines($action, $mysoc, null, GETPOST('lineid', 'int'), 1, '/bom/tpl'); 569 } 570 571 // Form to add new line 572 if ($object->status == 0 && $permissiontoadd && $action != 'selectlines') 573 { 574 if ($action != 'editline') 575 { 576 // Add products/services form 577 $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl'); 578 579 $parameters = array(); 580 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook 581 } 582 } 583 584 if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) 585 { 586 print '</table>'; 587 } 588 print '</div>'; 589 590 print "</form>\n"; 591 } 592 593 594 // Buttons for actions 595 596 if ($action != 'presend' && $action != 'editline') { 597 print '<div class="tabsAction">'."\n"; 598 $parameters = array(); 599 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook 600 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 601 602 if (empty($reshook)) 603 { 604 // Send 605 //if (empty($user->socid)) { 606 // print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=presend&mode=init#formmailbeforetitle">' . $langs->trans('SendMail') . '</a>'."\n"; 607 //} 608 609 // Back to draft 610 if ($object->status == $object::STATUS_VALIDATED) 611 { 612 if ($permissiontoadd) 613 { 614 print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=setdraft&token='.newToken().'">'.$langs->trans("SetToDraft").'</a>'; 615 } 616 } 617 618 // Modify 619 if ($object->status == $object::STATUS_DRAFT) 620 { 621 if ($permissiontoadd) 622 { 623 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken().'">'.$langs->trans("Modify").'</a>'."\n"; 624 } else { 625 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Modify').'</a>'."\n"; 626 } 627 } 628 629 // Validate 630 if ($object->status == $object::STATUS_DRAFT) 631 { 632 if ($permissiontoadd) 633 { 634 if (is_array($object->lines) && count($object->lines) > 0) 635 { 636 print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=validate&token='.newToken().'">'.$langs->trans("Validate").'</a>'; 637 } else { 638 $langs->load("errors"); 639 print '<a class="butActionRefused" href="" title="'.$langs->trans("ErrorAddAtLeastOneLineFirst").'">'.$langs->trans("Validate").'</a>'; 640 } 641 } 642 } 643 644 // Re-open 645 if ($permissiontoadd && $object->status == $object::STATUS_CANCELED) 646 { 647 print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=reopen">'.$langs->trans("ReOpen").'</a>'; 648 } 649 650 // Create MO 651 if ($conf->mrp->enabled) 652 { 653 if ($object->status == $object::STATUS_VALIDATED && !empty($user->rights->mrp->write)) 654 { 655 print '<a class="butAction" href="'.DOL_URL_ROOT.'/mrp/mo_card.php?action=create&fk_bom='.$object->id.'&backtopageforcancel='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id).'">'.$langs->trans("CreateMO").'</a>'; 656 } 657 } 658 659 // Clone 660 if ($permissiontoadd) 661 { 662 print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=clone&object=bom">'.$langs->trans("ToClone").'</a>'; 663 } 664 665 // Close / Cancel 666 if ($permissiontoadd && $object->status == $object::STATUS_VALIDATED) 667 { 668 print '<a class="butActionDelete" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=close">'.$langs->trans("Disable").'</a>'; 669 } 670 671 /* 672 if ($user->rights->bom->write) 673 { 674 if ($object->status == 1) 675 { 676 print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=disable">'.$langs->trans("Disable").'</a>'."\n"; 677 } 678 else 679 { 680 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=enable">'.$langs->trans("Enable").'</a>'."\n"; 681 } 682 } 683 */ 684 685 if ($permissiontodelete) 686 { 687 print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans('Delete').'</a>'."\n"; 688 } else { 689 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Delete').'</a>'."\n"; 690 } 691 } 692 print '</div>'."\n"; 693 } 694 695 696 // Select mail models is same action as presend 697 if (GETPOST('modelselected')) { 698 $action = 'presend'; 699 } 700 701 if ($action != 'presend') 702 { 703 print '<div class="fichecenter"><div class="fichehalfleft">'; 704 print '<a name="builddoc"></a>'; // ancre 705 706 // Documents 707 $objref = dol_sanitizeFileName($object->ref); 708 $relativepath = $objref.'/'.$objref.'.pdf'; 709 $filedir = $conf->bom->dir_output.'/'.$objref; 710 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; 711 $genallowed = $user->rights->bom->read; // If you can read, you can build the PDF to read content 712 $delallowed = $user->rights->bom->write; // If you can create/edit, you can remove a file on card 713 print $formfile->showdocuments('bom', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang); 714 715 // Show links to link elements 716 $linktoelem = $form->showLinkToObjectBlock($object, null, array('bom')); 717 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); 718 719 720 print '</div><div class="fichehalfright"><div class="ficheaddleft">'; 721 722 $MAXEVENT = 10; 723 724 $morehtmlright = '<a href="'.dol_buildpath('/bom/bom_agenda.php', 1).'?id='.$object->id.'">'; 725 $morehtmlright .= $langs->trans("SeeAll"); 726 $morehtmlright .= '</a>'; 727 728 // List of actions on element 729 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; 730 $formactions = new FormActions($db); 731 $somethingshown = $formactions->showactions($object, 'bom', $socid, 1, '', $MAXEVENT, '', $morehtmlright); 732 733 print '</div></div></div>'; 734 } 735 736 //Select mail models is same action as presend 737 if (GETPOST('modelselected')) $action = 'presend'; 738 739 // Presend form 740 $modelmail = 'bom'; 741 $defaulttopic = 'InformationMessage'; 742 $diroutput = $conf->bom->dir_output; 743 $trackid = 'bom'.$object->id; 744 745 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; 746} 747 748// End of page 749llxFooter(); 750$db->close(); 751