dolibarr 20.0.0
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
26require '../main.inc.php';
27require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
28require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
29require_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php';
30require_once DOL_DOCUMENT_ROOT.'/bom/lib/bom.lib.php';
31
32// Load translation files required by the page
33$langs->loadLangs(array("mrp", "other", "stocks"));
34
35// Get parameters
36$id = GETPOSTINT('id');
37$lineid = GETPOSTINT('lineid');
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 criteria
61$search_all = GETPOST("search_all", 'alpha');
62$search = array();
63foreach ($object->fields as $key => $val) {
64 if (GETPOST('search_'.$key, 'alpha')) {
65 $search[$key] = GETPOST('search_'.$key, 'alpha');
66 }
67}
68
69if (empty($action) && empty($id) && empty($ref)) {
70 $action = 'view';
71}
72
73// Load object
74include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once.
75if ($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
100if ($reshook < 0) {
101 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
102}
103
104if (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}
119
120
121/*
122 * View
123 */
124
125$form = new Form($db);
126$formfile = new FormFile($db);
127
128$title = $langs->trans('BOM');
129$help_url ='EN:Module_BOM';
130
131llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-bom page-net_needs');
132
133
134$TChildBom = array();
135if ($action == 'treeview') {
136 $object->getNetNeedsTree($TChildBom, 1);
137} else {
138 $object->getNetNeeds($TChildBom, 1);
139}
140
141
142// Part to show record
143if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) {
144 $head = bomPrepareHead($object);
145 print dol_get_fiche_head($head, 'net_needs', $langs->trans("BillOfMaterials"), -1, 'bom');
146
147 $formconfirm = '';
148
149 // Call Hook formConfirm
150 $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid);
151 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
152 if (empty($reshook)) {
153 $formconfirm .= $hookmanager->resPrint;
154 } elseif ($reshook > 0) {
155 $formconfirm = $hookmanager->resPrint;
156 }
157
158 // Print form confirm
159 print $formconfirm;
160
161
162 // Object card
163 // ------------------------------------------------------------
164 $linkback = '<a href="'.DOL_URL_ROOT.'/bom/bom_list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
165
166 $morehtmlref = '<div class="refidno">';
167
168 $morehtmlref .= '</div>';
169
170
171 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
172
173
174 print '<div class="fichecenter">';
175 print '<div class="fichehalfleft">';
176 print '<div class="underbanner clearboth"></div>';
177 print '<table class="border centpercent tableforfield">'."\n";
178
179 // Common attributes
180 $keyforbreak = 'duration';
181 include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_view.tpl.php';
182
183 print '<tr><td>'.$form->textwithpicto($langs->trans("TotalCost"), $langs->trans("BOMTotalCost")).'</td><td><span class="amount">'.price($object->total_cost).'</span></td></tr>';
184 print '<tr><td>'.$langs->trans("UnitCost").'</td><td>'.price($object->unit_cost).'</td></tr>';
185
186 // Other attributes
187 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
188
189 print '</table>';
190 print '</div>';
191 print '</div>';
192
193 print '<div class="clearboth"></div>';
194
195 print dol_get_fiche_end();
196
197 $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' : '')));
198 $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' : '')));
199
200 print load_fiche_titre($langs->trans("BOMNetNeeds"), $viewlink, 'product');
201
202 /*
203 * Lines
204 */
205 $text_stock_options = $langs->trans("RealStockDesc").'<br>';
206 $text_stock_options .= $langs->trans("RealStockWillAutomaticallyWhen").'<br>';
207 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT') || getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE') ? '- '.$langs->trans("DeStockOnShipment").'<br>' : '');
208 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_VALIDATE_ORDER') ? '- '.$langs->trans("DeStockOnValidateOrder").'<br>' : '');
209 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_BILL') ? '- '.$langs->trans("DeStockOnBill").'<br>' : '');
210 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_BILL') ? '- '.$langs->trans("ReStockOnBill").'<br>' : '');
211 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER') ? '- '.$langs->trans("ReStockOnValidateOrder").'<br>' : '');
212 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER') ? '- '.$langs->trans("ReStockOnDispatchOrder").'<br>' : '');
213 $text_stock_options .= (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE') ? '- '.$langs->trans("StockOnReception").'<br>' : '');
214
215 print '<table id="tablelines" class="noborder noshadow" width="100%">';
216 print "<thead>\n";
217 print '<tr class="liste_titre nodrag nodrop">';
218 print '<td class="linecoldescription">'.$langs->trans('Product');
219 if (getDolGlobalString('BOM_SUB_BOM') && $action == 'treeview') {
220 print ' &nbsp; <a id="show_all" href="#">'.img_picto('', 'folder-open', 'class="paddingright"').$langs->trans("ExpandAll").'</a>&nbsp;&nbsp;';
221 print '<a id="hide_all" href="#">'.img_picto('', 'folder', 'class="paddingright"').$langs->trans("UndoExpandAll").'</a>&nbsp;';
222 }
223 print '</td>';
224 if ($action == 'treeview') {
225 print '<td class="left">'.$langs->trans('ProducedBy').'</td>';
226 }
227 print '<td class="linecolqty right">'.$langs->trans('Quantity').'</td>';
228 print '<td></td>'; // For unit
229 print '<td class="linecolstock right">'.$form->textwithpicto($langs->trans("PhysicalStock"), $text_stock_options, 1).'</td>';
230 print '<td class="linecoltheoricalstock right">'.$form->textwithpicto($langs->trans("VirtualStock"), $langs->trans("VirtualStockDesc")).'</td>';
231 print '</tr>';
232
233 print '</thead>';
234 print '<tbody>';
235 if (!empty($TChildBom)) {
236 if ($action == 'treeview') {
237 foreach ($TChildBom as $fk_bom => $TProduct) {
238 $repeatChar = '&emsp;';
239 if (!empty($TProduct['bom'])) {
240 $prod = new Product($db);
241 $prod->fetch($TProduct['bom']->fk_product);
242 if ($TProduct['parentid'] != $object->id) {
243 print '<tr class="sub_bom_lines oddeven" parentid="'.$TProduct['parentid'].'">';
244 } else {
245 print '<tr class="oddeven">';
246 }
247 if ($action == 'treeview') {
248 print '<td class="linecoldescription">'.str_repeat($repeatChar, $TProduct['level']).$prod->getNomUrl(1);
249 } else {
250 print '<td class="linecoldescription">'.str_repeat($repeatChar, $TProduct['level']).$TProduct['bom']->getNomUrl(1);
251 }
252 print ' <a class="collapse_bom" id="collapse-'.$fk_bom.'" href="#">';
253 print img_picto('', 'folder-open');
254 print '</a>';
255 print '</td>';
256 if ($action == 'treeview') {
257 print '<td class="left">'.$TProduct['bom']->getNomUrl(1).'</td>';
258 }
259 print '<td class="linecolqty right">'.$TProduct['qty'].'</td>';
260 print '<td>';
261 print '</td>';
262 print '<td class="linecolstock right"></td>';
263 print '<td class="linecoltheoricalstock right"></td>';
264 print '</tr>';
265 }
266 if (!empty($TProduct['product'])) {
267 foreach ($TProduct['product'] as $fk_product => $TInfos) {
268 $prod = new Product($db);
269 $prod->fetch($fk_product);
270 $prod->load_virtual_stock();
271 if (empty($prod->stock_reel)) {
272 $prod->stock_reel = 0;
273 }
274 if ($fk_bom != $object->id) {
275 print '<tr class="sub_bom_lines oddeven" parentid="'.$fk_bom.'">';
276 } else {
277 print '<tr class="oddeven">';
278 }
279 print '<td class="linecoldescription">'.str_repeat($repeatChar, $TInfos['level']).$prod->getNomUrl(1).'</td>';
280 if ($action == 'treeview') {
281 print '<td></td>';
282 }
283 print '<td class="linecolqty right">'.$TInfos['qty'].'</td>';
284 print '<td>';
285 print '</td>';
286 print '<td class="linecolstock right">'.price2num($prod->stock_reel, 'MS').'</td>';
287 print '<td class="linecoltheoricalstock right">'.$prod->stock_theorique.'</td>';
288 print '</tr>';
289 }
290 }
291 }
292 } else {
293 foreach ($TChildBom as $fk_product => $elem) {
294 $prod = new Product($db);
295 $prod->fetch($fk_product);
296 $prod->load_virtual_stock();
297 if (empty($prod->stock_reel)) {
298 $prod->stock_reel = 0;
299 }
300 print '<tr class="oddeven">';
301 print '<td class="linecoldescription">'.$prod->getNomUrl(1).'</td>';
302 print '<td class="linecolqty right">'.$elem['qty'].'</td>';
303 print '<td>';
304 $useunit = (($prod->type == Product::TYPE_PRODUCT && getDolGlobalInt('PRODUCT_USE_UNITS')) || (($prod->type == Product::TYPE_SERVICE) && ($elem['fk_unit'])));
305 if ($useunit) {
306 require_once DOL_DOCUMENT_ROOT.'/core/class/cunits.class.php';
307 $unit = new CUnits($db);
308 $unit->fetch($elem['fk_unit']);
309 print(isset($unit->label) ? "&nbsp;".$langs->trans(ucwords($unit->label))."&nbsp;" : '');
310 }
311 print '</td>';
312 print '<td class="linecolstock right">'.price2num($prod->stock_reel, 'MS').'</td>';
313 print '<td class="linecoltheoricalstock right">'.$prod->stock_theorique.'</td>';
314 print '</tr>';
315 }
316 }
317 }
318 print '</tbody>';
319 print '</table>';
320
321
322
323 /*
324 * ButAction
325 */
326 print '<div class="tabsAction">'."\n";
327 $parameters = array();
328 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
329 if ($reshook < 0) {
330 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
331 }
332 print '</div>'; ?>
333
334 <script type="text/javascript" language="javascript">
335 $(document).ready(function() {
336
337 function folderManage(element) {
338 var id_bom_line = element.attr('id').replace('collapse-', '');
339 let TSubLines = $('[parentid="'+ id_bom_line +'"]');
340
341 if(element.html().indexOf('folder-open') <= 0) {
342 $('[parentid="'+ id_bom_line +'"]').show();
343 element.html('<?php echo dol_escape_js(img_picto('', 'folder-open')); ?>');
344 }
345 else {
346 for (let i = 0; i < TSubLines.length; i++) {
347 let subBomFolder = $(TSubLines[i]).children('.linecoldescription').children('.collapse_bom');
348 if (subBomFolder.length > 0) {
349 folderManage(subBomFolder);
350 }
351 }
352 TSubLines.hide();
353 element.html('<?php echo dol_escape_js(img_picto('', 'folder')); ?>');
354 }
355 }
356
357 // When clicking on collapse
358 $(".collapse_bom").click(function() {
359 folderManage($(this));
360 return false;
361 });
362
363 // To Show all the sub bom lines
364 $("#show_all").click(function() {
365 console.log("We click on show all");
366 $("[class^=sub_bom_lines]").show();
367 $("[class^=collapse_bom]").html('<?php echo dol_escape_js(img_picto('', 'folder-open')); ?>');
368 return false;
369 });
370
371 // To Hide all the sub bom lines
372 $("#hide_all").click(function() {
373 console.log("We click on hide all");
374 $("[class^=sub_bom_lines]").hide();
375 $("[class^=collapse_bom]").html('<?php echo dol_escape_js(img_picto('', 'folder')); ?>');
376 return false;
377 });
378
379 });
380 </script>
381
382 <?php
383}
384
385// End of page
386llxFooter();
387$db->close();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
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
bomPrepareHead($object)
Prepare array of tabs for BillOfMaterials.
Definition bom.lib.php:78
Class for BOM.
Definition bom.class.php:45
Class of dictionary type of thirdparty (used by imports)
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.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:139
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.