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