dolibarr  19.0.0-dev
product.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2006-2015 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
4  * Copyright (C) 2009-2010 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
6  * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com>
7  * Copyright (C) 2023 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  * or see https://www.gnu.org/
22  */
23 
36 function product_prepare_head($object)
37 {
38  global $db, $langs, $conf, $user;
39  $langs->load("products");
40 
41  $label = $langs->trans('Product');
42  $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('product', 'product_advance', 'read_prices'):$user->hasRight('product', 'read');
43 
44  if ($object->isService()) {
45  $label = $langs->trans('Service');
46  $usercancreadprice = getDolGlobalString('MAIN_USE_ADVANCED_PERMS')?$user->hasRight('service', 'service_advance', 'read_prices'):$user->hasRight('service', 'read');
47  }
48 
49  $h = 0;
50  $head = array();
51 
52  $head[$h][0] = DOL_URL_ROOT."/product/card.php?id=".$object->id;
53  $head[$h][1] = $label;
54  $head[$h][2] = 'card';
55  $h++;
56 
57  if (!empty($object->status)) {
58  if ($usercancreadprice) {
59  $head[$h][0] = DOL_URL_ROOT."/product/price.php?id=".$object->id;
60  $head[$h][1] = $langs->trans("SellingPrices");
61  $head[$h][2] = 'price';
62  $h++;
63  } else {
64  $head[$h][0] = '#';
65  $head[$h][1] = $langs->trans("SellingPrices");
66  $head[$h][2] = 'price';
67  $head[$h][5] = 'disabled';
68  $h++;
69  }
70  }
71 
72  if (!empty($object->status_buy) || (isModEnabled('margin') && !empty($object->status))) { // If margin is on and product on sell, we may need the cost price even if product os not on purchase
73  if ((isModEnabled("supplier_proposal") || isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) && ($user->hasRight('fournisseur', 'lire') || $user->hasRight('supplier_order', 'read') || $user->hasRight('supplier_invoice', 'read'))
74  || (isModEnabled('margin') && $user->hasRight("margin", "liretous"))
75  ) {
76  if ($usercancreadprice) {
77  $head[$h][0] = DOL_URL_ROOT."/product/fournisseurs.php?id=".$object->id;
78  $head[$h][1] = $langs->trans("BuyingPrices");
79  $head[$h][2] = 'suppliers';
80  $h++;
81  } else {
82  $head[$h][0] = '#';
83  $head[$h][1] = $langs->trans("BuyingPrices");
84  $head[$h][2] = 'suppliers';
85  $head[$h][5] = 'disabled';
86  $h++;
87  }
88  }
89  }
90 
91  // Multilangs
92  if (getDolGlobalInt('MAIN_MULTILANGS')) {
93  $head[$h][0] = DOL_URL_ROOT."/product/traduction.php?id=".$object->id;
94  $head[$h][1] = $langs->trans("Translations");
95  $head[$h][2] = 'translation';
96  $h++;
97  }
98 
99  // Sub products
100  if (!empty($conf->global->PRODUIT_SOUSPRODUITS)) {
101  $head[$h][0] = DOL_URL_ROOT."/product/composition/card.php?id=".$object->id;
102  $head[$h][1] = $langs->trans('AssociatedProducts');
103 
104  $nbFatherAndChild = $object->hasFatherOrChild();
105  if ($nbFatherAndChild > 0) {
106  $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbFatherAndChild.'</span>';
107  }
108  $head[$h][2] = 'subproduct';
109  $h++;
110  }
111 
112  if (isModEnabled('variants') && ($object->isProduct() || $object->isService())) {
113  global $db;
114 
115  require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
116 
117  $prodcomb = new ProductCombination($db);
118 
119  if ($prodcomb->fetchByFkProductChild($object->id) <= 0) {
120  $head[$h][0] = DOL_URL_ROOT."/variants/combinations.php?id=".$object->id;
121  $head[$h][1] = $langs->trans('ProductCombinations');
122  $head[$h][2] = 'combinations';
123  $nbVariant = $prodcomb->countNbOfCombinationForFkProductParent($object->id);
124  if ($nbVariant > 0) {
125  $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbVariant.'</span>';
126  }
127  }
128 
129  $h++;
130  }
131 
132  if ($object->isProduct() || ($object->isService() && !empty($conf->global->STOCK_SUPPORTS_SERVICES))) { // If physical product we can stock (or service with option)
133  if (isModEnabled('stock') && $user->hasRight('stock', 'lire')) {
134  $head[$h][0] = DOL_URL_ROOT."/product/stock/product.php?id=".$object->id;
135  $head[$h][1] = $langs->trans("Stock");
136  $head[$h][2] = 'stock';
137  $h++;
138  }
139  }
140 
141  // Tab to link resources
142  if (isModEnabled('resource')) {
143  if ($object->isProduct() && !empty($conf->global->RESOURCE_ON_PRODUCTS)) {
144  $head[$h][0] = DOL_URL_ROOT.'/resource/element_resource.php?element=product&ref='.$object->ref;
145  $head[$h][1] = $langs->trans("Resources");
146  $head[$h][2] = 'resources';
147  $h++;
148  }
149  if ($object->isService() && !empty($conf->global->RESOURCE_ON_SERVICES)) {
150  $head[$h][0] = DOL_URL_ROOT.'/resource/element_resource.php?element=service&ref='.$object->ref;
151  $head[$h][1] = $langs->trans("Resources");
152  $head[$h][2] = 'resources';
153  $h++;
154  }
155  }
156 
157  $head[$h][0] = DOL_URL_ROOT."/product/stats/facture.php?showmessage=1&id=".$object->id;
158  $head[$h][1] = $langs->trans('Referers');
159  $head[$h][2] = 'referers';
160  $h++;
161 
162  $head[$h][0] = DOL_URL_ROOT."/product/stats/card.php?id=".$object->id;
163  $head[$h][1] = $langs->trans('Statistics');
164  $head[$h][2] = 'stats';
165  $h++;
166 
167  // Show more tabs from modules
168  // Entries must be declared in modules descriptor with line
169  // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
170  // $this->tabs = array('entity:-tabname); to remove a tab
171  complete_head_from_modules($conf, $langs, $object, $head, $h, 'product', 'add', 'core');
172 
173  // Notes
174  if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
175  $nbNote = 0;
176  if (!empty($object->note_private)) {
177  $nbNote++;
178  }
179  if (!empty($object->note_public)) {
180  $nbNote++;
181  }
182  $head[$h][0] = DOL_URL_ROOT.'/product/note.php?id='.$object->id;
183  $head[$h][1] = $langs->trans('Notes');
184  if ($nbNote > 0) {
185  $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbNote.'</span>';
186  }
187  $head[$h][2] = 'note';
188  $h++;
189  }
190 
191  // Attachments
192  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
193  require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
194  if (isModEnabled("product") && ($object->type == Product::TYPE_PRODUCT)) {
195  $upload_dir = $conf->product->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
196  }
197  if (isModEnabled("service") && ($object->type == Product::TYPE_SERVICE)) {
198  $upload_dir = $conf->service->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
199  }
200  $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
201  if (getDolGlobalInt('PRODUCT_USE_OLD_PATH_FOR_PHOTO')) {
202  if (isModEnabled("product") && ($object->type == Product::TYPE_PRODUCT)) {
203  $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir($object->id, 2, 0, 0, $object, 'product').$object->id.'/photos';
204  }
205  if (isModEnabled("service") && ($object->type == Product::TYPE_SERVICE)) {
206  $upload_dir = $conf->service->multidir_output[$object->entity].'/'.get_exdir($object->id, 2, 0, 0, $object, 'product').$object->id.'/photos';
207  }
208  $nbFiles += count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
209  }
210  $nbLinks = Link::count($db, $object->element, $object->id);
211  $head[$h][0] = DOL_URL_ROOT.'/product/document.php?id='.$object->id;
212  $head[$h][1] = $langs->trans('Documents');
213  if (($nbFiles + $nbLinks) > 0) {
214  $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
215  }
216  $head[$h][2] = 'documents';
217  $h++;
218 
219  // Log
220  $head[$h][0] = DOL_URL_ROOT.'/product/agenda.php?id='.$object->id;
221  $head[$h][1] = $langs->trans("Events");
222  if (isModEnabled('agenda') && ($user->hasRight('agenda', 'myactions', 'read') || $user->hasRight('agenda', 'allactions', 'read'))) {
223  $head[$h][1] .= '/';
224  $head[$h][1] .= $langs->trans("Agenda");
225  }
226  $head[$h][2] = 'agenda';
227  $h++;
228 
229  complete_head_from_modules($conf, $langs, $object, $head, $h, 'product', 'add', 'external');
230 
231  complete_head_from_modules($conf, $langs, $object, $head, $h, 'product', 'remove');
232 
233  return $head;
234 }
235 
242 function productlot_prepare_head($object)
243 {
244  global $db, $langs, $conf, $user;
245 
246  // Load translation files required by the page
247  $langs->loadLangs(array("products", "productbatch"));
248 
249  $h = 0;
250  $head = array();
251 
252  $head[$h][0] = DOL_URL_ROOT."/product/stock/productlot_card.php?id=".$object->id;
253  $head[$h][1] = $langs->trans("Lot");
254  $head[$h][2] = 'card';
255  $h++;
256 
257  $head[$h][0] = DOL_URL_ROOT."/product/stock/stats/expedition.php?showmessage=1&id=".$object->id;
258  $head[$h][1] = $langs->trans('Referers');
259  $head[$h][2] = 'referers';
260  $h++;
261 
262  // Attachments
263  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
264  require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
265  $upload_dir = $conf->productbatch->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
266  $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
267  $nbLinks = Link::count($db, $object->element, $object->id);
268  $head[$h][0] = DOL_URL_ROOT."/product/stock/productlot_document.php?id=".$object->id;
269  $head[$h][1] = $langs->trans("Documents");
270  if (($nbFiles + $nbLinks) > 0) {
271  $head[$h][1] .= '<span class="badge marginleftonlyshort">'.($nbFiles + $nbLinks).'</span>';
272  }
273  $head[$h][2] = 'documents';
274  $h++;
275 
276  // Notes
277  if (empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
278  $nbNote = 0;
279  if (!empty($object->note_private)) {
280  $nbNote++;
281  }
282  if (!empty($object->note_public)) {
283  $nbNote++;
284  }
285  $head[$h][0] = DOL_URL_ROOT .'/product/stock/productlot_note.php?id=' . $object->id;
286  $head[$h][1] = $langs->trans('Notes');
287  if ($nbNote > 0) {
288  $head[$h][1] .= '<span class="badge marginleftonlyshort">' . $nbNote . '</span>';
289  }
290  $head[$h][2] = 'note';
291  $h++;
292  }
293 
294  // Show more tabs from modules
295  // Entries must be declared in modules descriptor with line
296  // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
297  // $this->tabs = array('entity:-tabname); to remove a tab
298  complete_head_from_modules($conf, $langs, $object, $head, $h, 'productlot');
299 
300  complete_head_from_modules($conf, $langs, $object, $head, $h, 'productlot', 'remove');
301 
302  // Log
303  /*
304  $head[$h][0] = DOL_URL_ROOT.'/product/info.php?id='.$object->id;
305  $head[$h][1] = $langs->trans("Info");
306  $head[$h][2] = 'info';
307  $h++;
308  */
309 
310  return $head;
311 }
312 
313 
314 
321 {
322  global $langs, $conf, $user, $db;
323 
324  $extrafields = new ExtraFields($db);
325  $extrafields->fetch_name_optionals_label('product');
326  $extrafields->fetch_name_optionals_label('product_fournisseur_price');
327 
328  $h = 0;
329  $head = array();
330 
331  $head[$h][0] = DOL_URL_ROOT."/product/admin/product.php";
332  $head[$h][1] = $langs->trans('Parameters');
333  $head[$h][2] = 'general';
334  $h++;
335 
336  if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($conf->global->PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL)) {
337  $head[$h] = array(
338  0 => DOL_URL_ROOT."/product/admin/price_rules.php",
339  1 => $langs->trans('MultipriceRules'),
340  2 => 'generator'
341  );
342  $h++;
343  }
344 
345  // Show more tabs from modules
346  // Entries must be declared in modules descriptor with line
347  // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
348  // $this->tabs = array('entity:-tabname); to remove a tab
349  complete_head_from_modules($conf, $langs, null, $head, $h, 'product_admin');
350 
351  $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_extrafields.php';
352  $head[$h][1] = $langs->trans("ExtraFields");
353  $nbExtrafields = $extrafields->attributes['product']['count'];
354  if ($nbExtrafields > 0) {
355  $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
356  }
357  $head[$h][2] = 'attributes';
358  $h++;
359 
360  $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_supplier_extrafields.php';
361  $head[$h][1] = $langs->trans("ProductSupplierExtraFields");
362  $nbExtrafields = $extrafields->attributes['product_fournisseur_price']['count'];
363  if ($nbExtrafields > 0) {
364  $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
365  }
366  $head[$h][2] = 'supplierAttributes';
367  $h++;
368 
369  complete_head_from_modules($conf, $langs, null, $head, $h, 'product_admin', 'remove');
370 
371  return $head;
372 }
373 
374 
375 
382 {
383  global $langs, $conf, $user, $db;
384 
385  $extrafields = new ExtraFields($db);
386  $extrafields->fetch_name_optionals_label('product_lot');
387 
388  $h = 0;
389  $head = array();
390 
391  $head[$h][0] = DOL_URL_ROOT."/product/admin/product_lot.php";
392  $head[$h][1] = $langs->trans('Parameters');
393  $head[$h][2] = 'settings';
394  $h++;
395 
396  // Show more tabs from modules
397  // Entries must be declared in modules descriptor with line
398  // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
399  // $this->tabs = array('entity:-tabname); to remove a tab
400  complete_head_from_modules($conf, $langs, null, $head, $h, 'product_lot_admin');
401 
402  $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_lot_extrafields.php';
403  $head[$h][1] = $langs->trans("ExtraFields");
404  $nbExtrafields = $extrafields->attributes['product_lot']['count'];
405  if ($nbExtrafields > 0) {
406  $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
407  }
408  $head[$h][2] = 'attributes';
409  $h++;
410 
411  complete_head_from_modules($conf, $langs, null, $head, $h, 'product_lot_admin', 'remove');
412 
413  return $head;
414 }
415 
416 
417 
425 function show_stats_for_company($product, $socid)
426 {
427  global $conf, $langs, $user, $db, $hookmanager;
428 
429  $form = new Form($db);
430 
431  $nblines = 0;
432 
433  print '<tr class="liste_titre">';
434  print '<td class="left" width="25%">'.$langs->trans("Referers").'</td>';
435  print '<td class="right" width="25%">'.$langs->trans("NbOfThirdParties").'</td>';
436  print '<td class="right" width="25%">'.$langs->trans("NbOfObjectReferers").'</td>';
437  print '<td class="right" width="25%">'.$langs->trans("TotalQuantity").'</td>';
438  print '</tr>';
439 
440  // Customer proposals
441  if (isModEnabled("propal") && $user->hasRight('propal', 'lire')) {
442  $nblines++;
443  $ret = $product->load_stats_propale($socid);
444  if ($ret < 0) {
445  dol_print_error($db);
446  }
447  $langs->load("propal");
448  print '<tr><td>';
449  print '<a href="propal.php?id='.$product->id.'">'.img_object('', 'propal', 'class="pictofixedwidth"').$langs->trans("Proposals").'</a>';
450  print '</td><td class="right">';
451  print $product->stats_propale['customers'];
452  print '</td><td class="right">';
453  print $product->stats_propale['nb'];
454  print '</td><td class="right">';
455  print $product->stats_propale['qty'];
456  print '</td>';
457  print '</tr>';
458  }
459  // Supplier proposals
460  if (isModEnabled('supplier_proposal') && $user->hasRight('supplier_proposal', 'lire')) {
461  $nblines++;
462  $ret = $product->load_stats_proposal_supplier($socid);
463  if ($ret < 0) {
464  dol_print_error($db);
465  }
466  $langs->load("supplier_proposal");
467  print '<tr><td>';
468  print '<a href="supplier_proposal.php?id='.$product->id.'">'.img_object('', 'supplier_proposal', 'class="pictofixedwidth"').$langs->trans("SupplierProposals").'</a>';
469  print '</td><td class="right">';
470  print $product->stats_proposal_supplier['suppliers'];
471  print '</td><td class="right">';
472  print $product->stats_proposal_supplier['nb'];
473  print '</td><td class="right">';
474  print $product->stats_proposal_supplier['qty'];
475  print '</td>';
476  print '</tr>';
477  }
478  // Sales orders
479  if (isModEnabled('commande') && $user->hasRight('commande', 'lire')) {
480  $nblines++;
481  $ret = $product->load_stats_commande($socid);
482  if ($ret < 0) {
483  dol_print_error($db);
484  }
485  $langs->load("orders");
486  print '<tr><td>';
487  print '<a href="commande.php?id='.$product->id.'">'.img_object('', 'order', 'class="pictofixedwidth"').$langs->trans("CustomersOrders").'</a>';
488  print '</td><td class="right">';
489  print $product->stats_commande['customers'];
490  print '</td><td class="right">';
491  print $product->stats_commande['nb'];
492  print '</td><td class="right">';
493  print $product->stats_commande['qty'];
494  print '</td>';
495  print '</tr>';
496  }
497  // Supplier orders
498  if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight('fournisseur', 'commande', 'lire')) || (isModEnabled("supplier_order") && $user->hasRight('supplier_order', 'lire'))) {
499  $nblines++;
500  $ret = $product->load_stats_commande_fournisseur($socid);
501  if ($ret < 0) {
502  dol_print_error($db);
503  }
504  $langs->load("orders");
505  print '<tr><td>';
506  print '<a href="commande_fournisseur.php?id='.$product->id.'">'.img_object('', 'supplier_order', 'class="pictofixedwidth"').$langs->trans("SuppliersOrders").'</a>';
507  print '</td><td class="right">';
508  print $product->stats_commande_fournisseur['suppliers'];
509  print '</td><td class="right">';
510  print $product->stats_commande_fournisseur['nb'];
511  print '</td><td class="right">';
512  print $product->stats_commande_fournisseur['qty'];
513  print '</td>';
514  print '</tr>';
515  }
516  // Customer invoices
517  if (isModEnabled('facture') && $user->hasRight('facture', 'lire')) {
518  $nblines++;
519  $ret = $product->load_stats_facture($socid);
520  if ($ret < 0) {
521  dol_print_error($db);
522  }
523  $langs->load("bills");
524  print '<tr><td>';
525  print '<a href="facture.php?id='.$product->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("CustomersInvoices").'</a>';
526  print '</td><td class="right">';
527  print $product->stats_facture['customers'];
528  print '</td><td class="right">';
529  print $product->stats_facture['nb'];
530  print '</td><td class="right">';
531  print $product->stats_facture['qty'];
532  print '</td>';
533  print '</tr>';
534  }
535  // Customer template invoices
536  if (isModEnabled("facture") && $user->hasRight('facture', 'lire')) {
537  $nblines++;
538  $ret = $product->load_stats_facturerec($socid);
539  if ($ret < 0) {
540  dol_print_error($db);
541  }
542  $langs->load("bills");
543  print '<tr><td>';
544  print '<a href="facturerec.php?id='.$product->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("RecurringInvoiceTemplate").'</a>';
545  print '</td><td class="right">';
546  print $product->stats_facture['customers'];
547  print '</td><td class="right">';
548  print $product->stats_facturerec['nb'];
549  print '</td><td class="right">';
550  print $product->stats_facturerec['qty'];
551  print '</td>';
552  print '</tr>';
553  }
554  // Supplier invoices
555  if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight('fournisseur', 'facture', 'lire')) || (isModEnabled("supplier_invoice") && $user->hasRight('supplier_invoice', 'lire'))) {
556  $nblines++;
557  $ret = $product->load_stats_facture_fournisseur($socid);
558  if ($ret < 0) {
559  dol_print_error($db);
560  }
561  $langs->load("bills");
562  print '<tr><td>';
563  print '<a href="facture_fournisseur.php?id='.$product->id.'">'.img_object('', 'supplier_invoice', 'class="pictofixedwidth"').$langs->trans("SuppliersInvoices").'</a>';
564  print '</td><td class="right">';
565  print $product->stats_facture_fournisseur['suppliers'];
566  print '</td><td class="right">';
567  print $product->stats_facture_fournisseur['nb'];
568  print '</td><td class="right">';
569  print $product->stats_facture_fournisseur['qty'];
570  print '</td>';
571  print '</tr>';
572  }
573 
574  // Contracts
575  if (isModEnabled('contrat') && $user->hasRight('contrat', 'lire')) {
576  $nblines++;
577  $ret = $product->load_stats_contrat($socid);
578  if ($ret < 0) {
579  dol_print_error($db);
580  }
581  $langs->load("contracts");
582  print '<tr><td>';
583  print '<a href="contrat.php?id='.$product->id.'">'.img_object('', 'contract', 'class="pictofixedwidth"').$langs->trans("Contracts").'</a>';
584  print '</td><td class="right">';
585  print $product->stats_contrat['customers'];
586  print '</td><td class="right">';
587  print $product->stats_contrat['nb'];
588  print '</td><td class="right">';
589  print $product->stats_contrat['qty'];
590  print '</td>';
591  print '</tr>';
592  }
593 
594  // BOM
595  if (isModEnabled('bom') && $user->hasRight('bom', 'read')) {
596  $nblines++;
597  $ret = $product->load_stats_bom($socid);
598  if ($ret < 0) {
599  setEventMessage($product->error, 'errors');
600  }
601  $langs->load("mrp");
602 
603  print '<tr><td>';
604  print '<a href="bom.php?id='.$product->id.'">'.img_object('', 'bom', 'class="pictofixedwidth"').$langs->trans("BOM").'</a>';
605  print '</td><td class="right">';
606 
607  print '</td><td class="right">';
608  print $form->textwithpicto($product->stats_bom['nb_toconsume'], $langs->trans("RowMaterial"));
609  print $form->textwithpicto($product->stats_bom['nb_toproduce'], $langs->trans("Finished"));
610  print '</td><td class="right">';
611  print $form->textwithpicto($product->stats_bom['qty_toconsume'], $langs->trans("RowMaterial"));
612  print $form->textwithpicto($product->stats_bom['qty_toproduce'], $langs->trans("Finished"));
613  print '</td>';
614  print '</tr>';
615  }
616 
617  // MO
618  if (isModEnabled('mrp') && !empty($user->rights->mrp->read)) {
619  $nblines++;
620  $ret = $product->load_stats_mo($socid);
621  if ($ret < 0) {
622  setEventMessages($product->error, $product->errors, 'errors');
623  }
624  $langs->load("mrp");
625  print '<tr><td>';
626  print '<a href="mo.php?id='.$product->id.'">'.img_object('', 'mrp', 'class="pictofixedwidth"').$langs->trans("MO").'</a>';
627  print '</td><td class="right">';
628  print $form->textwithpicto($product->stats_mo['customers_toconsume'], $langs->trans("ToConsume"));
629  print $form->textwithpicto($product->stats_mo['customers_consumed'], $langs->trans("QtyAlreadyConsumed"));
630  print $form->textwithpicto($product->stats_mo['customers_toproduce'], $langs->trans("QtyToProduce"));
631  print $form->textwithpicto($product->stats_mo['customers_produced'], $langs->trans("QtyAlreadyProduced"));
632  print '</td><td class="right">';
633  print $form->textwithpicto($product->stats_mo['nb_toconsume'], $langs->trans("ToConsume"));
634  print $form->textwithpicto($product->stats_mo['nb_consumed'], $langs->trans("QtyAlreadyConsumed"));
635  print $form->textwithpicto($product->stats_mo['nb_toproduce'], $langs->trans("QtyToProduce"));
636  print $form->textwithpicto($product->stats_mo['nb_produced'], $langs->trans("QtyAlreadyProduced"));
637  print '</td><td class="right">';
638  print $form->textwithpicto($product->stats_mo['qty_toconsume'], $langs->trans("ToConsume"));
639  print $form->textwithpicto($product->stats_mo['qty_consumed'], $langs->trans("QtyAlreadyConsumed"));
640  print $form->textwithpicto($product->stats_mo['qty_toproduce'], $langs->trans("QtyToProduce"));
641  print $form->textwithpicto($product->stats_mo['qty_produced'], $langs->trans("QtyAlreadyProduced"));
642  print '</td>';
643  print '</tr>';
644  }
645  $parameters = array('socid'=>$socid);
646  $reshook = $hookmanager->executeHooks('addMoreProductStat', $parameters, $product, $nblines); // Note that $action and $object may have been modified by some hooks
647  if ($reshook < 0) {
648  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
649  }
650 
651  print $hookmanager->resPrint;
652 
653 
654  return $nblines++;
655 }
656 
664 function show_stats_for_batch($batch, $socid)
665 {
666  global $conf, $langs, $user, $db, $hookmanager;
667 
668  $langs->LoadLangs(array('sendings', 'orders', 'receptions'));
669 
670  $form = new Form($db);
671 
672  $nblines = 0;
673 
674  print '<tr class="liste_titre">';
675  print '<td class="left" width="25%">'.$langs->trans("Referers").'</td>';
676  print '<td class="right" width="25%">'.$langs->trans("NbOfThirdParties").'</td>';
677  print '<td class="right" width="25%">'.$langs->trans("NbOfObjectReferers").'</td>';
678  print '<td class="right" width="25%">'.$langs->trans("TotalQuantity").'</td>';
679  print '</tr>';
680 
681  // Expeditions
682  if (isModEnabled('expedition') && !empty($user->rights->expedition->lire)) {
683  $nblines++;
684  $ret = $batch->loadStatsExpedition($socid);
685  if ($ret < 0) {
686  dol_print_error($db);
687  }
688  $langs->load("bills");
689  print '<tr><td>';
690  print '<a href="'.dol_buildpath('/product/stock/stats/expedition.php', 1).'?id='.$batch->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("Shipments").'</a>';
691  print '</td><td class="right">';
692  print $batch->stats_expedition['customers'];
693  print '</td><td class="right">';
694  print $batch->stats_expedition['nb'];
695  print '</td><td class="right">';
696  print $batch->stats_expedition['qty'];
697  print '</td>';
698  print '</tr>';
699  }
700 
701  if (isModEnabled("reception") && !empty($user->rights->reception->lire)) {
702  $nblines++;
703  $ret = $batch->loadStatsReception($socid);
704  if ($ret < 0) {
705  dol_print_error($db);
706  }
707  $langs->load("bills");
708  print '<tr><td>';
709  print '<a href="'.dol_buildpath('/product/stock/stats/reception.php', 1).'?id='.$batch->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("Receptions").'</a>';
710  print '</td><td class="right">';
711  print $batch->stats_reception['customers'];
712  print '</td><td class="right">';
713  print $batch->stats_reception['nb'];
714  print '</td><td class="right">';
715  print $batch->stats_reception['qty'];
716  print '</td>';
717  print '</tr>';
718  } elseif (isModEnabled('supplier_order') && !empty($user->rights->fournisseur->commande->lire)) {
719  $nblines++;
720  $ret = $batch->loadStatsSupplierOrder($socid);
721  if ($ret < 0) {
722  dol_print_error($db);
723  }
724  $langs->load("bills");
725  print '<tr><td>';
726  print '<a href="'.dol_buildpath('/product/stock/stats/commande_fournisseur.php', 1).'?id='.$batch->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("SuppliersOrders").'</a>';
727  print '</td><td class="right">';
728  print $batch->stats_supplier_order['customers'];
729  print '</td><td class="right">';
730  print $batch->stats_supplier_order['nb'];
731  print '</td><td class="right">';
732  print $batch->stats_supplier_order['qty'];
733  print '</td>';
734  print '</tr>';
735  }
736 
737  if (isModEnabled('mrp') && !empty($user->rights->mrp->read)) {
738  $nblines++;
739  $ret = $batch->loadStatsMo($socid);
740  if ($ret < 0) {
741  dol_print_error($db);
742  }
743  $langs->load("mrp");
744  print '<tr><td>';
745  print '<a href="'.dol_buildpath('/product/stock/stats/mo.php', 1).'?id='.$batch->id.'">'.img_object('', 'mrp', 'class="pictofixedwidth"').$langs->trans("MO").'</a>';
746  print '</td><td class="right">';
747  // print $form->textwithpicto($batch->stats_mo['customers_toconsume'], $langs->trans("ToConsume")); Makes no sense with batch, at this moment we don't know batch number
748  print $form->textwithpicto($batch->stats_mo['customers_consumed'], $langs->trans("QtyAlreadyConsumed"));
749  // print $form->textwithpicto($batch->stats_mo['customers_toproduce'], $langs->trans("QtyToProduce")); Makes no sense with batch, at this moment we don't know batch number
750  print $form->textwithpicto($batch->stats_mo['customers_produced'], $langs->trans("QtyAlreadyProduced"));
751  print '</td><td class="right">';
752  // print $form->textwithpicto($batch->stats_mo['nb_toconsume'], $langs->trans("ToConsume")); Makes no sense with batch, at this moment we don't know batch number
753  print $form->textwithpicto($batch->stats_mo['nb_consumed'], $langs->trans("QtyAlreadyConsumed"));
754  // print $form->textwithpicto($batch->stats_mo['nb_toproduce'], $langs->trans("QtyToProduce")); Makes no sense with batch, at this moment we don't know batch number
755  print $form->textwithpicto($batch->stats_mo['nb_produced'], $langs->trans("QtyAlreadyProduced"));
756  print '</td><td class="right">';
757  // print $form->textwithpicto($batch->stats_mo['qty_toconsume'], $langs->trans("ToConsume")); Makes no sense with batch, at this moment we don't know batch number
758  print $form->textwithpicto($batch->stats_mo['qty_consumed'], $langs->trans("QtyAlreadyConsumed"));
759  // print $form->textwithpicto($batch->stats_mo['qty_toproduce'], $langs->trans("QtyToProduce")); Makes no sense with batch, at this moment we don't know batch number
760  print $form->textwithpicto($batch->stats_mo['qty_produced'], $langs->trans("QtyAlreadyProduced"));
761  print '</td>';
762  print '</tr>';
763  }
764 
765  $parameters = array('socid'=>$socid);
766  $reshook = $hookmanager->executeHooks('addMoreBatchProductStat', $parameters, $batch, $nblines); // Note that $action and $object may have been modified by some hooks
767  if ($reshook < 0) {
768  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
769  }
770 
771  print $hookmanager->resPrint;
772 
773 
774  return $nblines++;
775 }
776 
789 function measuring_units_string($scale = '', $measuring_style = '', $unit = 0, $use_short_label = 0, $outputlangs = null)
790 {
791  return measuringUnitString($unit, $measuring_style, $scale, $use_short_label, $outputlangs);
792 }
793 
805 function measuringUnitString($unit, $measuring_style = '', $scale = '', $use_short_label = 0, $outputlangs = null)
806 {
807  global $langs, $db;
808  global $measuring_unit_cache;
809 
810  if (empty($outputlangs)) {
811  $outputlangs = $langs;
812  }
813 
814  if (empty($measuring_unit_cache[$unit.'_'.$measuring_style.'_'.$scale.'_'.$use_short_label])) {
815  require_once DOL_DOCUMENT_ROOT.'/core/class/cunits.class.php';
816  $measuringUnits = new CUnits($db);
817 
818  if ($measuring_style == '' && $scale == '') {
819  $arrayforfilter = array(
820  't.rowid' => $unit,
821  't.active' => 1
822  );
823  } elseif ($scale !== '') {
824  $arrayforfilter = array(
825  't.scale' => $scale,
826  't.unit_type' => $measuring_style,
827  't.active' => 1
828  );
829  } else {
830  $arrayforfilter = array(
831  't.rowid' => $unit,
832  't.unit_type' => $measuring_style,
833  't.active' => 1
834  );
835  }
836  $result = $measuringUnits->fetchAll('', '', 0, 0, $arrayforfilter);
837 
838  if ($result < 0) {
839  return -1;
840  } else {
841  if (is_array($measuringUnits->records) && count($measuringUnits->records) > 0) {
842  if ($use_short_label) {
843  $labeltoreturn = $measuringUnits->records[key($measuringUnits->records)]->short_label;
844  } else {
845  $labeltoreturn = $outputlangs->transnoentitiesnoconv($measuringUnits->records[key($measuringUnits->records)]->label);
846  }
847  } else {
848  $labeltoreturn = '';
849  }
850  $measuring_unit_cache[$unit.'_'.$measuring_style.'_'.$scale.'_'.$use_short_label] = $labeltoreturn;
851  return $labeltoreturn;
852  }
853  } else {
854  return $measuring_unit_cache[$unit.'_'.$measuring_style.'_'.$scale.'_'.$use_short_label];
855  }
856 }
857 
865 function measuring_units_squared($unit)
866 {
867  $measuring_units = array();
868  $measuring_units[0] = 0; // m -> m3
869  $measuring_units[-1] = -2; // dm-> dm2
870  $measuring_units[-2] = -4; // cm -> cm2
871  $measuring_units[-3] = -6; // mm -> mm2
872  $measuring_units[98] = 98; // foot -> foot2
873  $measuring_units[99] = 99; // inch -> inch2
874  return $measuring_units[$unit];
875 }
876 
877 
885 function measuring_units_cubed($unit)
886 {
887  $measuring_units = array();
888  $measuring_units[0] = 0; // m -> m2
889  $measuring_units[-1] = -3; // dm-> dm3
890  $measuring_units[-2] = -6; // cm -> cm3
891  $measuring_units[-3] = -9; // mm -> mm3
892  $measuring_units[98] = 88; // foot -> foot3
893  $measuring_units[99] = 89; // inch -> inch3
894  return $measuring_units[$unit];
895 }
dol_sanitizeFileName
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
Definition: functions.lib.php:1323
ProductCombination
Class ProductCombination Used to represent a product combination.
Definition: ProductCombination.class.php:24
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:5107
measuring_units_squared
measuring_units_squared($unit)
Transform a given unit scale into the square of that unit, if known.
Definition: product.lib.php:865
dol_dir_list
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:62
product_prepare_head
product_prepare_head($object)
Prepare array with list of tabs.
Definition: product.lib.php:36
$form
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
setEventMessage
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
Definition: functions.lib.php:8637
productlot_prepare_head
productlot_prepare_head($object)
Prepare array with list of tabs.
Definition: product.lib.php:242
measuringUnitString
measuringUnitString($unit, $measuring_style='', $scale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
Definition: product.lib.php:805
measuring_units_string
measuring_units_string($scale='', $measuring_style='', $unit=0, $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
Definition: product.lib.php:789
get_exdir
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
Definition: functions.lib.php:6882
complete_head_from_modules
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode='add', $filterorigmodule='')
Complete or removed entries into a head array (used to build tabs).
Definition: functions.lib.php:9602
product_lot_admin_prepare_head
product_lot_admin_prepare_head()
Return array head with list of tabs to view object informations.
Definition: product.lib.php:381
show_stats_for_batch
show_stats_for_batch($batch, $socid)
Show stats for product batch.
Definition: product.lib.php:664
CUnits
Class of dictionary type of thirdparty (used by imports)
Definition: cunits.class.php:28
product_admin_prepare_head
product_admin_prepare_head()
Return array head with list of tabs to view object informations.
Definition: product.lib.php:320
setEventMessages
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
Definition: functions.lib.php:8673
isModEnabled
isModEnabled($module)
Is Dolibarr module enabled.
Definition: functions.lib.php:207
getDolGlobalString
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
Definition: functions.lib.php:142
measuring_units_cubed
measuring_units_cubed($unit)
Transform a given unit scale into the cube of that unit, if known.
Definition: product.lib.php:885
ExtraFields
Class to manage standard extra fields.
Definition: extrafields.class.php:39
Form
Class to manage generation of HTML components Only common components must be here.
Definition: html.form.class.php:53
img_object
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
Definition: functions.lib.php:4473
show_stats_for_company
show_stats_for_company($product, $socid)
Show stats for company.
Definition: product.lib.php:425
Product\TYPE_SERVICE
const TYPE_SERVICE
Service.
Definition: product.class.php:577
Product\TYPE_PRODUCT
const TYPE_PRODUCT
Regular product.
Definition: product.class.php:573
getDolGlobalInt
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
Definition: functions.lib.php:156