dolibarr  17.0.3
bom_card.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2017-2023 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 
25 // Load Dolibarr environment
26 require '../main.inc.php';
27 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
28 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
29 require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/bom/lib/bom.lib.php';
31 require_once DOL_DOCUMENT_ROOT.'/mrp/lib/mrp.lib.php';
32 
33 
34 // Load translation files required by the page
35 $langs->loadLangs(array('mrp', 'other'));
36 
37 // Get parameters
38 $id = GETPOST('id', 'int');
39 $lineid = GETPOST('lineid', 'int');
40 $ref = GETPOST('ref', 'alpha');
41 $action = GETPOST('action', 'aZ09');
42 $confirm = GETPOST('confirm', 'alpha');
43 $cancel = GETPOST('cancel', 'aZ09');
44 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'bomcard'; // To manage different context of search
45 $backtopage = GETPOST('backtopage', 'alpha');
46 
47 
48 // PDF
49 $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
50 $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
51 $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
52 
53 // Initialize technical objects
54 $object = new BOM($db);
55 $extrafields = new ExtraFields($db);
56 $diroutputmassaction = $conf->bom->dir_output.'/temp/massgeneration/'.$user->id;
57 $hookmanager->initHooks(array('bomcard', 'globalcard')); // Note that conf->hooks_modules contains array
58 
59 // Fetch optionals attributes and labels
60 $extrafields->fetch_name_optionals_label($object->table_element);
61 $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
62 
63 // Initialize array of search criterias
64 $search_all = GETPOST("search_all", 'alpha');
65 $search = array();
66 foreach ($object->fields as $key => $val) {
67  if (GETPOST('search_'.$key, 'alpha')) {
68  $search[$key] = GETPOST('search_'.$key, 'alpha');
69  }
70 }
71 
72 if (empty($action) && empty($id) && empty($ref)) {
73  $action = 'view';
74 }
75 
76 // Load object
77 include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once.
78 if ($object->id > 0) {
79  $object->calculateCosts();
80 }
81 
82 
83 // Security check - Protection if external user
84 //if ($user->socid > 0) accessforbidden();
85 //if ($user->socid > 0) $socid = $user->socid;
86 $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
87 $result = restrictedArea($user, 'bom', $object->id, 'bom_bom', '', '', 'rowid', $isdraft);
88 
89 // Permissions
90 $permissionnote = $user->rights->bom->write; // Used by the include of actions_setnotes.inc.php
91 $permissiondellink = $user->rights->bom->write; // Used by the include of actions_dellink.inc.php
92 $permissiontoadd = $user->rights->bom->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
93 $permissiontodelete = $user->rights->bom->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT);
94 $upload_dir = $conf->bom->multidir_output[isset($object->entity) ? $object->entity : 1];
95 
96 
97 /*
98  * Actions
99  */
100 
101 $parameters = array();
102 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
103 if ($reshook < 0) {
104  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
105 }
106 
107 if (empty($reshook)) {
108  $error = 0;
109 
110  $backurlforlist = DOL_URL_ROOT.'/bom/bom_list.php';
111 
112  if (empty($backtopage) || ($cancel && empty($id))) {
113  if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
114  if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
115  $backtopage = $backurlforlist;
116  } else {
117  $backtopage = DOL_URL_ROOT.'/bom/bom_card.php?id='.($id > 0 ? $id : '__ID__');
118  }
119  }
120  }
121 
122  $triggermodname = 'BOM_MODIFY'; // Name of trigger action code to execute when we modify record
123 
124 
125  // Actions cancel, add, update, delete or clone
126  include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php';
127  // The fetch/fetch_lines was redone into the inc.php so we must recall the calculateCosts()
128  if ($action == 'confirm_validate' && $object->id > 0) {
129  $object->calculateCosts();
130  }
131 
132  // Actions when linking object each other
133  include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php';
134 
135  // Actions when printing a doc from card
136  include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
137 
138  // Action to move up and down lines of object
139  //include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php';
140 
141  // Action to build doc
142  include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
143 
144  // Actions to send emails
145  $triggersendname = 'BOM_SENTBYMAIL';
146  $autocopy = 'MAIN_MAIL_AUTOCOPY_BOM_TO';
147  $trackid = 'bom'.$object->id;
148  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
149 
150  // Add line
151  if ($action == 'addline' && $user->rights->bom->write) {
152  $langs->load('errors');
153  $error = 0;
154  $predef = '';
155 
156  // Set if we used free entry or predefined product
157  $bom_child_id = (int) GETPOST('bom_id', 'int');
158  if ($bom_child_id > 0) {
159  $bom_child = new BOM($db);
160  $res = $bom_child->fetch($bom_child_id);
161  if ($res) {
162  $idprod = $bom_child->fk_product;
163  }
164  } else {
165  $idprod = (!empty(GETPOST('idprodservice', 'int')) ? GETPOST('idprodservice', 'int') : (int) GETPOST('idprod', 'int'));
166  }
167 
168  $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
169  $qty_frozen = price2num(GETPOST('qty_frozen', 'alpha'), 'MS');
170  $disable_stock_change = GETPOST('disable_stock_change', 'int');
171  $efficiency = price2num(GETPOST('efficiency', 'alpha'));
172  $fk_unit = GETPOST('fk_unit', 'alphanohtml');
173  if ($qty == '') {
174  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
175  $error++;
176  }
177  if (!($idprod > 0)) {
178  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Product')), null, 'errors');
179  $error++;
180  }
181 
182  if ($object->fk_product == $idprod) {
183  setEventMessages($langs->trans('TheProductXIsAlreadyTheProductToProduce'), null, 'errors');
184  $error++;
185  }
186 
187  // We check if we're allowed to add this bom
188  $TParentBom=array();
189  $object->getParentBomTreeRecursive($TParentBom);
190  if ($bom_child_id > 0 && !empty($TParentBom) && in_array($bom_child_id, $TParentBom)) {
191  $n_child = new BOM($db);
192  $n_child->fetch($bom_child_id);
193  setEventMessages($langs->transnoentities('BomCantAddChildBom', $n_child->getNomUrl(1), $object->getNomUrl(1)), null, 'errors');
194  $error++;
195  }
196 
197  if (!$error) {
198  // Extrafields
199  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
200  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
201  // Unset extrafield
202  if (is_array($extralabelsline)) {
203  // Get extra fields
204  foreach ($extralabelsline as $key => $value) {
205  unset($_POST["options_".$key]);
206  }
207  }
208 
209  $result = $object->addLine($idprod, $qty, $qty_frozen, $disable_stock_change, $efficiency, -1, $bom_child_id, null, $fk_unit, $array_options);
210 
211  if ($result <= 0) {
212  setEventMessages($object->error, $object->errors, 'errors');
213  $action = '';
214  } else {
215  unset($_POST['idprod']);
216  unset($_POST['idprodservice']);
217  unset($_POST['qty']);
218  unset($_POST['qty_frozen']);
219  unset($_POST['disable_stock_change']);
220  }
221 
222  $object->fetchLines();
223 
224  $object->calculateCosts();
225  }
226  }
227 
228  // Update line
229  if ($action == 'updateline' && $user->rights->bom->write) {
230  $langs->load('errors');
231  $error = 0;
232 
233  // Set if we used free entry or predefined product
234  $qty = price2num(GETPOST('qty', 'alpha'), 'MS');
235  $qty_frozen = price2num(GETPOST('qty_frozen', 'alpha'), 'MS');
236  $disable_stock_change = GETPOST('disable_stock_change', 'int');
237  $efficiency = price2num(GETPOST('efficiency', 'alpha'));
238  $fk_unit = GETPOST('fk_unit', 'alphanohtml');
239 
240  if ($qty == '') {
241  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
242  $error++;
243  }
244 
245  if (!$error) {
246  // Extrafields
247  $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
248  $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
249  // Unset extrafield
250  if (is_array($extralabelsline)) {
251  // Get extra fields
252  foreach ($extralabelsline as $key => $value) {
253  unset($_POST["options_".$key]);
254  }
255  }
256 
257  $bomline = new BOMLine($db);
258  $bomline->fetch($lineid);
259 
260  $result = $object->updateLine($lineid, $qty, (int) $qty_frozen, (int) $disable_stock_change, $efficiency, $bomline->position, $bomline->import_key, $fk_unit, $array_options);
261 
262  if ($result <= 0) {
263  setEventMessages($object->error, $object->errors, 'errors');
264  $action = '';
265  } else {
266  unset($_POST['idprod']);
267  unset($_POST['idprodservice']);
268  unset($_POST['qty']);
269  unset($_POST['qty_frozen']);
270  unset($_POST['disable_stock_change']);
271  }
272 
273  $object->fetchLines();
274 
275  $object->calculateCosts();
276  }
277  }
278 }
279 
280 
281 /*
282  * View
283  */
284 
285 $form = new Form($db);
286 $formfile = new FormFile($db);
287 
288 
289 $title = $langs->trans('BOM');
290 $help_url ='EN:Module_BOM';
291 llxHeader('', $title, $help_url);
292 
293 // Part to create
294 if ($action == 'create') {
295  print load_fiche_titre($langs->trans("NewBOM"), '', 'bom');
296 
297  print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
298  print '<input type="hidden" name="token" value="'.newToken().'">';
299  print '<input type="hidden" name="action" value="add">';
300  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
301 
302  print dol_get_fiche_head(array(), '');
303 
304  print '<table class="border centpercent tableforfieldcreate">'."\n";
305 
306  // Common attributes
307  include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_add.tpl.php';
308 
309  // Other attributes
310  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
311 
312  print '</table>'."\n";
313 
314  print dol_get_fiche_end();
315 
316  print $form->buttonsSaveCancel("Create");
317 
318  print '</form>';
319 }
320 
321 // Part to edit record
322 if (($id || $ref) && $action == 'edit') {
323  print load_fiche_titre($langs->trans("BillOfMaterials"), '', 'cubes');
324 
325  print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
326  print '<input type="hidden" name="token" value="'.newToken().'">';
327  print '<input type="hidden" name="action" value="update">';
328  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
329  print '<input type="hidden" name="id" value="'.$object->id.'">';
330 
331  print dol_get_fiche_head();
332 
333  //$object->fields['keyfield']['disabled'] = 1;
334 
335  print '<table class="border centpercent tableforfieldedit">'."\n";
336 
337  // Common attributes
338  include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_edit.tpl.php';
339 
340  // Other attributes
341  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php';
342 
343  print '</table>';
344 
345  print dol_get_fiche_end();
346 
347  print $form->buttonsSaveCancel("Create");
348 
349  print '</form>';
350 }
351 
352 // Part to show record
353 if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) {
354  $head = bomPrepareHead($object);
355  print dol_get_fiche_head($head, 'card', $langs->trans("BillOfMaterials"), -1, 'bom');
356 
357  $formconfirm = '';
358 
359  // Confirmation to delete
360  if ($action == 'delete') {
361  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteBillOfMaterials'), $langs->trans('ConfirmDeleteBillOfMaterials'), 'confirm_delete', '', 0, 1);
362  }
363  // Confirmation to delete line
364  if ($action == 'deleteline') {
365  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1);
366  }
367 
368  // Confirmation of validation
369  if ($action == 'validate') {
370  // We check that object has a temporary ref
371  $ref = substr($object->ref, 1, 4);
372  if ($ref == 'PROV') {
373  $object->fetch_product();
374  $numref = $object->getNextNumRef($object->product);
375  } else {
376  $numref = $object->ref;
377  }
378 
379  $text = $langs->trans('ConfirmValidateBom', $numref);
380  /*if (isModEnabled('notification'))
381  {
382  require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
383  $notify = new Notify($db);
384  $text .= '<br>';
385  $text .= $notify->confirmMessage('BOM_VALIDATE', $object->socid, $object);
386  }*/
387 
388  $formquestion = array();
389  if (isModEnabled('bom')) {
390  $langs->load("mrp");
391  $forcecombo = 0;
392  if ($conf->browser->name == 'ie') {
393  $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
394  }
395  $formquestion = array(
396  // 'text' => $langs->trans("ConfirmClone"),
397  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
398  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
399  );
400  }
401 
402  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('Validate'), $text, 'confirm_validate', $formquestion, 0, 1, 220);
403  }
404 
405  // Confirmation of closing
406  if ($action == 'close') {
407  $text = $langs->trans('ConfirmCloseBom', $object->ref);
408  /*if (isModEnabled('notification'))
409  {
410  require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
411  $notify = new Notify($db);
412  $text .= '<br>';
413  $text .= $notify->confirmMessage('BOM_CLOSE', $object->socid, $object);
414  }*/
415 
416  $formquestion = array();
417  if (isModEnabled('bom')) {
418  $langs->load("mrp");
419  $forcecombo = 0;
420  if ($conf->browser->name == 'ie') {
421  $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
422  }
423  $formquestion = array(
424  // 'text' => $langs->trans("ConfirmClone"),
425  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
426  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
427  );
428  }
429 
430  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('Close'), $text, 'confirm_close', $formquestion, 0, 1, 220);
431  }
432 
433  // Confirmation of reopen
434  if ($action == 'reopen') {
435  $text = $langs->trans('ConfirmReopenBom', $object->ref);
436  /*if (isModEnabled('notification'))
437  {
438  require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
439  $notify = new Notify($db);
440  $text .= '<br>';
441  $text .= $notify->confirmMessage('BOM_CLOSE', $object->socid, $object);
442  }*/
443 
444  $formquestion = array();
445  if (isModEnabled('bom')) {
446  $langs->load("mrp");
447  require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
448  $forcecombo = 0;
449  if ($conf->browser->name == 'ie') {
450  $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
451  }
452  $formquestion = array(
453  // 'text' => $langs->trans("ConfirmClone"),
454  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
455  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
456  );
457  }
458 
459  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ReOpen'), $text, 'confirm_reopen', $formquestion, 0, 1, 220);
460  }
461 
462  // Clone confirmation
463  if ($action == 'clone') {
464  // Create an array for form
465  $formquestion = array();
466  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('ToClone'), $langs->trans('ConfirmCloneBillOfMaterials', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
467  }
468 
469  // Confirmation of action xxxx
470  if ($action == 'setdraft') {
471  $text = $langs->trans('ConfirmSetToDraft', $object->ref);
472 
473  $formquestion = array();
474  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('SetToDraft'), $text, 'confirm_setdraft', $formquestion, 0, 1, 220);
475  }
476 
477  // Call Hook formConfirm
478  $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
479  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
480  if (empty($reshook)) {
481  $formconfirm .= $hookmanager->resPrint;
482  } elseif ($reshook > 0) {
483  $formconfirm = $hookmanager->resPrint;
484  }
485 
486  // Print form confirm
487  print $formconfirm;
488 
489 
490  // Object card
491  // ------------------------------------------------------------
492  $linkback = '<a href="'.DOL_URL_ROOT.'/bom/bom_list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
493 
494  $morehtmlref = '<div class="refidno">';
495  /*
496  // Ref bis
497  $morehtmlref.=$form->editfieldkey("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->bom->creer, 'string', '', 0, 1);
498  $morehtmlref.=$form->editfieldval("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->bom->creer, 'string', '', null, null, '', 1);
499  // Thirdparty
500  $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1);
501  // Project
502  if (isModEnabled('project'))
503  {
504  $langs->load("projects");
505  $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
506  if ($permissiontoadd)
507  {
508  if ($action != 'classify')
509  $morehtmlref.='<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&token='.newToken().'&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
510  if ($action == 'classify') {
511  //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
512  $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
513  $morehtmlref.='<input type="hidden" name="action" value="classin">';
514  $morehtmlref.='<input type="hidden" name="token" value="'.newToken().'">';
515  $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1);
516  $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
517  $morehtmlref.='</form>';
518  } else {
519  $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
520  }
521  } else {
522  if (! empty($object->fk_project)) {
523  $proj = new Project($db);
524  $proj->fetch($object->fk_project);
525  $morehtmlref.=$proj->getNomUrl();
526  } else {
527  $morehtmlref.='';
528  }
529  }
530  }
531  */
532  $morehtmlref .= '</div>';
533 
534 
535  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
536 
537 
538  print '<div class="fichecenter">';
539  print '<div class="fichehalfleft">';
540  print '<div class="underbanner clearboth"></div>';
541  print '<table class="border centpercent tableforfield">'."\n";
542 
543  // Common attributes
544  $keyforbreak = 'duration';
545  include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php';
546  $object->calculateCosts();
547  print '<tr><td>'.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).'</td><td><span class="amount">'.price($object->total_cost).'</span></td></tr>';
548  print '<tr><td>'.$langs->trans("UnitCost").'</td><td>'.price($object->unit_cost).'</td></tr>';
549 
550  // Other attributes
551  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
552 
553  print '</table>';
554  print '</div>';
555  print '</div>';
556 
557  print '<div class="clearboth"></div>';
558 
559  print dol_get_fiche_end();
560 
561 
562 
563  /*
564  * Lines
565  */
566 
567  if (!empty($object->table_element_line)) {
568  // Products
569  $res = $object->fetchLinesbytypeproduct(0); // Load all lines products into ->lines
570  $object->calculateCosts();
571 
572  print ($res == 0 && $object->status >= $object::STATUS_VALIDATED) ? '' : load_fiche_titre($langs->trans('BOMProductsList'), '', 'product');
573 
574  print ' <form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . (($action != 'editline') ? '' : '') . '" method="POST">
575  <input type="hidden" name="token" value="' . newToken() . '">
576  <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline') . '">
577  <input type="hidden" name="mode" value="">
578  <input type="hidden" name="page_y" value="">
579  <input type="hidden" name="id" value="' . $object->id . '">
580  ';
581 
582  if (!empty($conf->use_javascript_ajax) && $object->status == 0) {
583  include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
584  }
585 
586  print '<div class="div-table-responsive-no-min">';
587  if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
588  print '<table id="tablelines" class="noborder noshadow centpercent">';
589  }
590 
591  if (!empty($object->lines)) {
592  $object->printObjectLines($action, $mysoc, null, GETPOST('lineid', 'int'), 1, '/bom/tpl');
593  }
594 
595  // Form to add new line
596  if ($object->status == 0 && $permissiontoadd && $action != 'selectlines') {
597  if ($action != 'editline') {
598  // Add products/services form
599 
600 
601  $parameters = array();
602  $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
603  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
604  if (empty($reshook))
605  $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl');
606  }
607  }
608 
609  if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
610  print '</table>';
611  }
612  print '</div>';
613 
614  print "</form>\n";
615 
616  // Services
617  $filtertype = 1;
618  $res = $object->fetchLinesbytypeproduct(1); // Load all lines services into ->lines
619  $object->calculateCosts();
620 
621  print ($res == 0 && $object->status >= $object::STATUS_VALIDATED) ? '' : load_fiche_titre($langs->trans('BOMServicesList'), '', 'service');
622 
623  print ' <form name="addservice" id="addservice" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . (($action != 'editline') ? '' : '') . '" method="POST">
624  <input type="hidden" name="token" value="' . newToken() . '">
625  <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline') . '">
626  <input type="hidden" name="mode" value="">
627  <input type="hidden" name="page_y" value=""> <input type="hidden" name="id" value="' . $object->id . '">
628  ';
629 
630  if (!empty($conf->use_javascript_ajax) && $object->status == 0) {
631  $tagidfortablednd = 'tablelinesservice';
632  include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
633  }
634 
635  print '<div class="div-table-responsive-no-min">';
636  if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
637  print '<table id="tablelinesservice" class="noborder noshadow centpercent">';
638  }
639 
640  if (!empty($object->lines)) {
641  $object->printObjectLines($action, $mysoc, null, GETPOST('lineid', 'int'), 1, '/bom/tpl');
642  }
643 
644  // Form to add new line
645  if ($object->status == 0 && $permissiontoadd && $action != 'selectlines') {
646  if ($action != 'editline') {
647  // Add services form
648  $parameters = array();
649  $reshook = $hookmanager->executeHooks('formAddObjectServiceLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
650  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
651  if (empty($reshook))
652  $object->formAddObjectLine(1, $mysoc, null, '/bom/tpl');
653  }
654  }
655  }
656 
657  if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
658  print '</table>';
659  }
660  print '</div>';
661 
662  print "</form>\n";
663 
664 
666 
667 
668  $res = $object->fetchLines();
669 
670  // Buttons for actions
671 
672  if ($action != 'presend' && $action != 'editline') {
673  print '<div class="tabsAction">'."\n";
674  $parameters = array();
675  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
676  if ($reshook < 0) {
677  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
678  }
679 
680  if (empty($reshook)) {
681  // Send
682  //if (empty($user->socid)) {
683  // print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=presend&mode=init#formmailbeforetitle">' . $langs->trans('SendMail') . '</a>'."\n";
684  //}
685 
686  // Back to draft
687  if ($object->status == $object::STATUS_VALIDATED) {
688  if ($permissiontoadd) {
689  print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=setdraft&token='.newToken().'">'.$langs->trans("SetToDraft").'</a>'."\n";
690  }
691  }
692 
693  // Modify
694  if ($object->status == $object::STATUS_DRAFT) {
695  if ($permissiontoadd) {
696  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit&token='.newToken().'">'.$langs->trans("Modify").'</a>'."\n";
697  } else {
698  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans('Modify').'</a>'."\n";
699  }
700  }
701 
702  // Validate
703  if ($object->status == $object::STATUS_DRAFT) {
704  if ($permissiontoadd) {
705  if (is_array($object->lines) && count($object->lines) > 0) {
706  print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&amp;action=validate&amp;token='.newToken().'">'.$langs->trans("Validate").'</a>'."\n";
707  } else {
708  $langs->load("errors");
709  print '<a class="butActionRefused" href="" title="'.$langs->trans("ErrorAddAtLeastOneLineFirst").'">'.$langs->trans("Validate").'</a>'."\n";
710  }
711  }
712  }
713 
714  // Re-open
715  if ($permissiontoadd && $object->status == $object::STATUS_CANCELED) {
716  print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>'."\n";
717  }
718 
719  // Create MO
720  if (isModEnabled('mrp')) {
721  if ($object->status == $object::STATUS_VALIDATED && !empty($user->rights->mrp->write)) {
722  print '<a class="butAction" href="'.DOL_URL_ROOT.'/mrp/mo_card.php?action=create&fk_bom='.$object->id.'&token='.newToken().'&backtopageforcancel='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id).'">'.$langs->trans("CreateMO").'</a>'."\n";
723  }
724  }
725 
726  // Clone
727  if ($permissiontoadd) {
728  print dolGetButtonAction($langs->trans("ToClone"), '', 'default', $_SERVER['PHP_SELF'].'?id='.$object->id.(!empty($object->socid) ? '&socid='.$object->socid : "").'&action=clone&object=bom', 'clone', $permissiontoadd);
729  }
730 
731  // Close / Cancel
732  if ($permissiontoadd && $object->status == $object::STATUS_VALIDATED) {
733  print '<a class="butActionDelete" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=close&token='.newToken().'">'.$langs->trans("Disable").'</a>'."\n";
734  }
735 
736  /*
737  if ($user->rights->bom->write)
738  {
739  if ($object->status == 1)
740  {
741  print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=disable&token='.newToken().'">'.$langs->trans("Disable").'</a>'."\n";
742  }
743  else
744  {
745  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=enable&token='.newToken().'">'.$langs->trans("Enable").'</a>'."\n";
746  }
747  }
748  */
749 
750  // Delete
751  print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), 'delete', $permissiontodelete);
752  }
753  print '</div>'."\n";
754  }
755 
756 
757  // Select mail models is same action as presend
758  if (GETPOST('modelselected')) {
759  $action = 'presend';
760  }
761 
762  if ($action != 'presend') {
763  print '<div class="fichecenter"><div class="fichehalfleft">';
764  print '<a name="builddoc"></a>'; // ancre
765 
766  // Documents
767  $objref = dol_sanitizeFileName($object->ref);
768  $relativepath = $objref.'/'.$objref.'.pdf';
769  $filedir = $conf->bom->dir_output.'/'.$objref;
770  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
771  $genallowed = $user->rights->bom->read; // If you can read, you can build the PDF to read content
772  $delallowed = $user->rights->bom->write; // If you can create/edit, you can remove a file on card
773  print $formfile->showdocuments('bom', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang);
774 
775  // Show links to link elements
776  $linktoelem = $form->showLinkToObjectBlock($object, null, array('bom'));
777  $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
778 
779 
780  print '</div><div class="fichehalfright">';
781 
782  $MAXEVENT = 10;
783 
784  $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/bom/bom_agenda.php?id='.$object->id);
785 
786  // List of actions on element
787  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
788  $formactions = new FormActions($db);
789  $somethingshown = $formactions->showactions($object, $object->element, 0, 1, '', $MAXEVENT, '', $morehtmlcenter);
790 
791  print '</div></div>';
792  }
793 
794  //Select mail models is same action as presend
795  if (GETPOST('modelselected')) {
796  $action = 'presend';
797  }
798 
799  // Presend form
800  $modelmail = 'bom';
801  $defaulttopic = 'InformationMessage';
802  $diroutput = $conf->bom->dir_output;
803  $trackid = 'bom'.$object->id;
804 
805  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
806 }
807 
808 
809 // End of page
810 llxFooter();
811 $db->close();
dol_sanitizeFileName
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
Definition: functions.lib.php:1225
llxFooter
llxFooter()
Empty footer.
Definition: wrapper.php:70
load_fiche_titre
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
Definition: functions.lib.php:5360
GETPOST
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Definition: functions.lib.php:520
FormActions
Class to manage building of HTML components.
Definition: html.formactions.class.php:30
BOMLine
Class for BOMLine.
Definition: bom.class.php:1544
$form
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
BOM
Class for BOM.
Definition: bom.class.php:36
dol_banner_tab
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
Definition: functions.lib.php:2082
$help_url
if(GETPOST('button_removefilter_x', 'alpha')||GETPOST('button_removefilter.x', 'alpha')||GETPOST('button_removefilter', 'alpha')) if(GETPOST('button_search_x', 'alpha')||GETPOST('button_search.x', 'alpha')||GETPOST('button_search', 'alpha')) if($action=="save" &&empty($cancel)) $help_url
View.
Definition: agenda.php:118
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5823
mrpCollapseBomManagement
mrpCollapseBomManagement()
Manage collapse bom display.
Definition: bom.lib.php:152
llxHeader
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
$formactions
if(preg_match('/set_([a-z0-9_\-]+)/i', $action, $reg)) if(preg_match('/del_([a-z0-9_\-]+)/i', $action, $reg)) if($action=='set') elseif($action=='specimen') elseif($action=='setmodel') elseif($action=='del') elseif($action=='setdoc') $formactions
View.
Definition: agenda_other.php:179
$formconfirm
$formconfirm
if ($action == 'delbookkeepingyear') {
Definition: listbyaccount.php:614
FormFile
Class to offer components to list and upload files.
Definition: html.formfile.class.php:36
dolGetButtonTitle
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.
Definition: functions.lib.php:11021
bomPrepareHead
bomPrepareHead($object)
Prepare array of tabs for BillOfMaterials.
Definition: bom.lib.php:78
dol_get_fiche_head
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='')
Show tabs of a record.
Definition: functions.lib.php:1858
restrictedArea
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.
Definition: security.lib.php:346
newToken
newToken()
Return the value of token currently saved into session with name 'newtoken'.
Definition: functions.lib.php:11294
dol_get_fiche_end
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition: functions.lib.php:2054
isModEnabled
isModEnabled($module)
Is Dolibarr module enabled.
Definition: functions.lib.php:137
dolGetButtonAction
dolGetButtonAction($label, $text='', $actionType='default', $url='', $id='', $userRight=1, $params=array())
Function dolGetButtonAction.
Definition: functions.lib.php:10857
ExtraFields
Class to manage standard extra fields.
Definition: extrafields.class.php:39
Form
Class to manage generation of HTML components Only common components must be here.
Definition: html.form.class.php:53
price
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.
Definition: functions.lib.php:5697
setEventMessages
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
Definition: functions.lib.php:8465