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