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