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 }
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 a product combination.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
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
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $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 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.
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:36
product_admin_prepare_head()
Return array head with list of tabs to view object informations.
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 informations.
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.