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