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