dolibarr  19.0.0-dev
bom_net_needs.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2017-2020 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17  */
18 
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 
32 // Load translation files required by the page
33 $langs->loadLangs(array("mrp", "other", "stocks"));
34 
35 // Get parameters
36 $id = GETPOST('id', 'int');
37 $lineid = GETPOST('lineid', 'int');
38 $ref = GETPOST('ref', 'alpha');
39 $action = GETPOST('action', 'aZ09');
40 $confirm = GETPOST('confirm', 'alpha');
41 $cancel = GETPOST('cancel', 'aZ09');
42 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'bomnet_needs'; // To manage different context of search
43 $backtopage = GETPOST('backtopage', 'alpha');
44 
45 
46 // Initialize technical objects
47 $object = new BOM($db);
48 $extrafields = new ExtraFields($db);
49 
50 // Initialize technical objects for hooks
51 $hookmanager->initHooks(array('bomnetneeds')); // Note that conf->hooks_modules contains array
52 
53 // Massaction
54 $diroutputmassaction = $conf->bom->dir_output.'/temp/massgeneration/'.$user->id;
55 
56 // Fetch optionals attributes and labels
57 $extrafields->fetch_name_optionals_label($object->table_element);
58 $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
59 
60 // Initialize array of search criterias
61 $search_all = GETPOST("search_all", 'alpha');
62 $search = array();
63 foreach ($object->fields as $key => $val) {
64  if (GETPOST('search_'.$key, 'alpha')) {
65  $search[$key] = GETPOST('search_'.$key, 'alpha');
66  }
67 }
68 
69 if (empty($action) && empty($id) && empty($ref)) {
70  $action = 'view';
71 }
72 
73 // Load object
74 include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once.
75 if ($object->id > 0) {
76  $object->calculateCosts();
77 }
78 
79 
80 // Security check - Protection if external user
81 //if ($user->socid > 0) accessforbidden();
82 //if ($user->socid > 0) $socid = $user->socid;
83 $isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
84 $result = restrictedArea($user, 'bom', $object->id, $object->table_element, '', '', 'rowid', $isdraft);
85 
86 // Permissions
87 $permissionnote = $user->hasRight('bom', 'write'); // Used by the include of actions_setnotes.inc.php
88 $permissiondellink = $user->hasRight('bom', 'write'); // Used by the include of actions_dellink.inc.php
89 $permissiontoadd = $user->hasRight('bom', 'write'); // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
90 $permissiontodelete = $user->hasRight('bom', 'delete') || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT);
91 $upload_dir = $conf->bom->multidir_output[isset($object->entity) ? $object->entity : 1];
92 
93 
94 /*
95  * Actions
96  */
97 
98 $parameters = array();
99 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
100 if ($reshook < 0) {
101  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
102 }
103 
104 if (empty($reshook)) {
105  $error = 0;
106 
107  $backurlforlist = DOL_URL_ROOT.'/bom/bom_list.php';
108 
109  if (empty($backtopage) || ($cancel && empty($id))) {
110  if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
111  if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
112  $backtopage = $backurlforlist;
113  } else {
114  $backtopage = DOL_URL_ROOT.'/bom/bom_net_needs.php?id='.($id > 0 ? $id : '__ID__');
115  }
116  }
117  }
118  if ($action == 'treeview') $object->getNetNeedsTree($TChildBom, 1);
119  else $object->getNetNeeds($TChildBom, 1);
120 }
121 
122 
123 /*
124  * View
125  */
126 
127 $form = new Form($db);
128 $formfile = new FormFile($db);
129 
130 $title = $langs->trans('BOM');
131 $help_url ='EN:Module_BOM';
132 llxHeader('', $title, $help_url);
133 
134 
135 // Part to show record
136 if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) {
137  $head = bomPrepareHead($object);
138  print dol_get_fiche_head($head, 'net_needs', $langs->trans("BillOfMaterials"), -1, 'bom');
139 
140  $formconfirm = '';
141 
142  // Call Hook formConfirm
143  $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
144  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
145  if (empty($reshook)) {
146  $formconfirm .= $hookmanager->resPrint;
147  } elseif ($reshook > 0) {
148  $formconfirm = $hookmanager->resPrint;
149  }
150 
151  // Print form confirm
152  print $formconfirm;
153 
154 
155  // Object card
156  // ------------------------------------------------------------
157  $linkback = '<a href="'.DOL_URL_ROOT.'/bom/bom_list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
158 
159  $morehtmlref = '<div class="refidno">';
160 
161  $morehtmlref .= '</div>';
162 
163 
164  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
165 
166 
167  print '<div class="fichecenter">';
168  print '<div class="fichehalfleft">';
169  print '<div class="underbanner clearboth"></div>';
170  print '<table class="border centpercent tableforfield">'."\n";
171 
172  // Common attributes
173  $keyforbreak = 'duration';
174  include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php';
175 
176  print '<tr><td>'.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).'</td><td><span class="amount">'.price($object->total_cost).'</span></td></tr>';
177  print '<tr><td>'.$langs->trans("UnitCost").'</td><td>'.price($object->unit_cost).'</td></tr>';
178 
179  // Other attributes
180  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
181 
182  print '</table>';
183  print '</div>';
184  print '</div>';
185 
186  print '<div class="clearboth"></div>';
187 
188  print dol_get_fiche_end();
189 
190  $viewlink = dolGetButtonTitle($langs->trans('GroupByX', $langs->transnoentitiesnoconv("Products")), '', 'fa fa-bars imgforviewmode', $_SERVER['PHP_SELF'].'?id='.$object->id.'&token='.newToken(), '', 1, array('morecss' => 'reposition '.($action !== 'treeview' ? 'btnTitleSelected':'')));
191  $viewlink .= dolGetButtonTitle($langs->trans('TreeView'), '', 'fa fa-stream imgforviewmode', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=treeview&token='.newToken(), '', 1, array('morecss' => 'reposition marginleftonly '.($action == 'treeview' ? 'btnTitleSelected':'')));
192 
193  print load_fiche_titre($langs->trans("BOMNetNeeds"), $viewlink, 'product');
194 
195  /*
196  * Lines
197  */
198  $text_stock_options = $langs->trans("RealStockDesc").'<br>';
199  $text_stock_options .= $langs->trans("RealStockWillAutomaticallyWhen").'<br>';
200  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT) || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE) ? '- '.$langs->trans("DeStockOnShipment").'<br>' : '');
201  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) ? '- '.$langs->trans("DeStockOnValidateOrder").'<br>' : '');
202  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_BILL) ? '- '.$langs->trans("DeStockOnBill").'<br>' : '');
203  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL) ? '- '.$langs->trans("ReStockOnBill").'<br>' : '');
204  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER) ? '- '.$langs->trans("ReStockOnValidateOrder").'<br>' : '');
205  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER) ? '- '.$langs->trans("ReStockOnDispatchOrder").'<br>' : '');
206  $text_stock_options .= (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE) ? '- '.$langs->trans("StockOnReception").'<br>' : '');
207 
208  print '<table id="tablelines" class="noborder noshadow" width="100%">';
209  print "<thead>\n";
210  print '<tr class="liste_titre nodrag nodrop">';
211  print '<td class="linecoldescription">'.$langs->trans('Product');
212  if (!empty($conf->global->BOM_SUB_BOM) && $action == 'treeview') {
213  print ' &nbsp; <a id="show_all" href="#">'.img_picto('', 'folder-open', 'class="paddingright"').$langs->trans("ExpandAll").'</a>&nbsp;&nbsp;';
214  print '<a id="hide_all" href="#">'.img_picto('', 'folder', 'class="paddingright"').$langs->trans("UndoExpandAll").'</a>&nbsp;';
215  }
216  print '</td>';
217  if ($action == 'treeview') print '<td class="left">'.$langs->trans('ProducedBy').'</td>';
218  print '<td class="linecolqty right">'.$langs->trans('Quantity').'</td>';
219  print '<td class="linecolstock right">'.$form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1).'</td>';
220  print '<td class="linecoltheoricalstock right">'.$form->textwithpicto($langs->trans("VirtualStock"), $langs->trans("VirtualStockDesc")).'</td>';
221  print '</tr>';
222 
223  print '</thead>';
224  print '<tbody>';
225  if (!empty($TChildBom)) {
226  if ($action == 'treeview') {
227  foreach ($TChildBom as $fk_bom => $TProduct) {
228  $repeatChar = '&emsp;';
229  if (!empty($TProduct['bom'])) {
230  $prod = new Product($db);
231  $prod->fetch($TProduct['bom']->fk_product);
232  if ($TProduct['parentid'] != $object->id) print '<tr class="sub_bom_lines oddeven" parentid="'.$TProduct['parentid'].'">';
233  else print '<tr class="oddeven">';
234  if ($action == 'treeview') print '<td class="linecoldescription">'.str_repeat($repeatChar, $TProduct['level']).$prod->getNomUrl(1);
235  else print '<td class="linecoldescription">'.str_repeat($repeatChar, $TProduct['level']).$TProduct['bom']->getNomUrl(1);
236  print ' <a class="collapse_bom" id="collapse-'.$fk_bom.'" href="#">';
237  print img_picto('', 'folder-open');
238  print '</a>';
239  print '</td>';
240  if ($action == 'treeview') print '<td class="left">'.$TProduct['bom']->getNomUrl(1).'</td>';
241  print '<td class="linecolqty right">'.$TProduct['qty'].'</td>';
242  print '<td class="linecolstock right"></td>';
243  print '<td class="linecoltheoricalstock right"></td>';
244  print '</tr>';
245  }
246  if (!empty($TProduct['product'])) {
247  foreach ($TProduct['product'] as $fk_product => $TInfos) {
248  $prod = new Product($db);
249  $prod->fetch($fk_product);
250  $prod->load_virtual_stock();
251  if (empty($prod->stock_reel)) $prod->stock_reel = 0;
252  if ($fk_bom != $object->id) print '<tr class="sub_bom_lines oddeven" parentid="'.$fk_bom.'">';
253  else print '<tr class="oddeven">';
254  print '<td class="linecoldescription">'.str_repeat($repeatChar, $TInfos['level']).$prod->getNomUrl(1).'</td>';
255  if ($action == 'treeview') print '<td></td>';
256  print '<td class="linecolqty right">'.$TInfos['qty'].'</td>';
257  print '<td class="linecolstock right">'.price2num($prod->stock_reel, 'MS').'</td>';
258  print '<td class="linecoltheoricalstock right">'.$prod->stock_theorique.'</td>';
259  print '</tr>';
260  }
261  }
262  }
263  } else {
264  foreach ($TChildBom as $fk_product => $qty) {
265  $prod = new Product($db);
266  $prod->fetch($fk_product);
267  $prod->load_virtual_stock();
268  if (empty($prod->stock_reel)) $prod->stock_reel = 0;
269  print '<tr class="oddeven">';
270  print '<td class="linecoldescription">'.$prod->getNomUrl(1).'</td>';
271  print '<td class="linecolqty right">'.$qty.'</td>';
272  print '<td class="linecolstock right">'.price2num($prod->stock_reel, 'MS').'</td>';
273  print '<td class="linecoltheoricalstock right">'.$prod->stock_theorique.'</td>';
274  print '</tr>';
275  }
276  }
277  }
278  print '</tbody>';
279  print '</table>';
280 
281 
282 
283  /*
284  * ButAction
285  */
286  print '<div class="tabsAction">'."\n";
287  $parameters = array();
288  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
289  if ($reshook < 0) {
290  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
291  }
292  print '</div>';
293 
294 
295  ?>
296 
297  <script type="text/javascript" language="javascript">
298  $(document).ready(function() {
299 
300  function folderManage(element) {
301  var id_bom_line = element.attr('id').replace('collapse-', '');
302  let TSubLines = $('[parentid="'+ id_bom_line +'"]');
303 
304  if(element.html().indexOf('folder-open') <= 0) {
305  $('[parentid="'+ id_bom_line +'"]').show();
306  element.html('<?php echo dol_escape_js(img_picto('', 'folder-open')); ?>');
307  }
308  else {
309  for (let i = 0; i < TSubLines.length; i++) {
310  let subBomFolder = $(TSubLines[i]).children('.linecoldescription').children('.collapse_bom');
311  if (subBomFolder.length > 0) {
312  folderManage(subBomFolder);
313  }
314  }
315  TSubLines.hide();
316  element.html('<?php echo dol_escape_js(img_picto('', 'folder')); ?>');
317  }
318  }
319 
320  // When clicking on collapse
321  $(".collapse_bom").click(function() {
322  folderManage($(this));
323  return false;
324  });
325 
326  // To Show all the sub bom lines
327  $("#show_all").click(function() {
328  console.log("We click on show all");
329  $("[class^=sub_bom_lines]").show();
330  $("[class^=collapse_bom]").html('<?php echo dol_escape_js(img_picto('', 'folder-open')); ?>');
331  return false;
332  });
333 
334  // To Hide all the sub bom lines
335  $("#hide_all").click(function() {
336  console.log("We click on hide all");
337  $("[class^=sub_bom_lines]").hide();
338  $("[class^=collapse_bom]").html('<?php echo dol_escape_js(img_picto('', 'folder')); ?>');
339  return false;
340  });
341 
342  });
343  </script>
344 
345  <?php
346 }
347 
348 // End of page
349 llxFooter();
350 $db->close();
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
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
bomPrepareHead($object)
Prepare array of tabs for BillOfMaterials.
Definition: bom.lib.php:78
Class for BOM.
Definition: bom.class.php:43
Class to manage standard extra fields.
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.
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
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.
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.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
newToken()
Return the value of token currently saved into session with name 'newtoken'.
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.
$formconfirm
if ($action == 'delbookkeepingyear') {
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:120
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.