dolibarr 21.0.0-beta
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, $user, $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 $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_price_extrafields.php';
372 $head[$h][1] = $langs->trans("ProductLevelExtraFields");
373 $nbExtrafields = $extrafields->attributes['product_price']['count'];
374 if ($nbExtrafields > 0) {
375 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
376 }
377 $head[$h][2] = 'levelAttributes';
378 $h++;
379
380 $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_customer_extrafields.php';
381 $head[$h][1] = $langs->trans("ProductCustomerExtraFields");
382 $nbExtrafields = $extrafields->attributes['product_customer_price']['count'];
383 if ($nbExtrafields > 0) {
384 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
385 }
386 $head[$h][2] = 'customerAttributes';
387 $h++;
388
389 $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_supplier_extrafields.php';
390 $head[$h][1] = $langs->trans("ProductSupplierExtraFields");
391 $nbExtrafields = $extrafields->attributes['product_fournisseur_price']['count'];
392 if ($nbExtrafields > 0) {
393 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
394 }
395 $head[$h][2] = 'supplierAttributes';
396 $h++;
397
398 complete_head_from_modules($conf, $langs, null, $head, $h, 'product_admin', 'remove');
399
400 return $head;
401}
402
403
404
411{
412 global $langs, $conf, $user, $db;
413
414 $extrafields = new ExtraFields($db);
415 $extrafields->fetch_name_optionals_label('product_lot');
416
417 $h = 0;
418 $head = array();
419
420 $head[$h][0] = DOL_URL_ROOT."/product/admin/product_lot.php";
421 $head[$h][1] = $langs->trans('Parameters');
422 $head[$h][2] = 'settings';
423 $h++;
424
425 // Show more tabs from modules
426 // Entries must be declared in modules descriptor with line
427 // $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
428 // $this->tabs = array('entity:-tabname); to remove a tab
429 complete_head_from_modules($conf, $langs, null, $head, $h, 'product_lot_admin');
430
431 $head[$h][0] = DOL_URL_ROOT.'/product/admin/product_lot_extrafields.php';
432 $head[$h][1] = $langs->trans("ExtraFields");
433 $nbExtrafields = $extrafields->attributes['product_lot']['count'];
434 if ($nbExtrafields > 0) {
435 $head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbExtrafields.'</span>';
436 }
437 $head[$h][2] = 'attributes';
438 $h++;
439
440 complete_head_from_modules($conf, $langs, null, $head, $h, 'product_lot_admin', 'remove');
441
442 return $head;
443}
444
445
446
454function show_stats_for_company($product, $socid)
455{
456 global $langs, $user, $db, $hookmanager;
457
458 $form = new Form($db);
459
460 $nblines = 0;
461
462 print '<tr class="liste_titre">';
463 print '<td class="left" width="25%">'.$langs->trans("Referers").'</td>';
464 print '<td class="right" width="25%">'.$langs->trans("NbOfThirdParties").'</td>';
465 print '<td class="right" width="25%">'.$langs->trans("NbOfObjectReferers").'</td>';
466 print '<td class="right" width="25%">'.$langs->trans("TotalQuantity").'</td>';
467 print '</tr>';
468
469 // Customer proposals
470 if (isModEnabled("propal") && $user->hasRight('propal', 'lire')) {
471 $nblines++;
472 $ret = $product->load_stats_propale($socid);
473 if ($ret < 0) {
474 dol_print_error($db);
475 }
476 $langs->load("propal");
477 print '<tr><td>';
478 print '<a href="'.DOL_URL_ROOT.'/product/stats/propal.php?id='.$product->id.'">'.img_object('', 'propal', 'class="pictofixedwidth"').$langs->trans("Proposals").'</a>';
479 print '</td><td class="right">';
480 print $product->stats_propale['customers'];
481 print '</td><td class="right">';
482 print $product->stats_propale['nb'];
483 print '</td><td class="right">';
484 print price($product->stats_propale['qty'], 1, $langs, 0, 0);
485 print '</td>';
486 print '</tr>';
487 }
488 // Supplier proposals
489 if (isModEnabled('supplier_proposal') && $user->hasRight('supplier_proposal', 'lire')) {
490 $nblines++;
491 $ret = $product->load_stats_proposal_supplier($socid);
492 if ($ret < 0) {
493 dol_print_error($db);
494 }
495 $langs->load("supplier_proposal");
496 print '<tr><td>';
497 print '<a href="'.DOL_URL_ROOT.'/product/stats/supplier_proposal.php?id='.$product->id.'">'.img_object('', 'supplier_proposal', 'class="pictofixedwidth"').$langs->trans("SupplierProposals").'</a>';
498 print '</td><td class="right">';
499 print $product->stats_proposal_supplier['suppliers'];
500 print '</td><td class="right">';
501 print $product->stats_proposal_supplier['nb'];
502 print '</td><td class="right">';
503 print price($product->stats_proposal_supplier['qty'], 1, $langs, 0, 0);
504 print '</td>';
505 print '</tr>';
506 }
507 // Sales orders
508 if (isModEnabled('order') && $user->hasRight('commande', 'lire')) {
509 $nblines++;
510 $ret = $product->load_stats_commande($socid);
511 if ($ret < 0) {
512 dol_print_error($db);
513 }
514 $langs->load("orders");
515 print '<tr><td>';
516 print '<a href="'.DOL_URL_ROOT.'/product/stats/commande.php?id='.$product->id.'">'.img_object('', 'order', 'class="pictofixedwidth"').$langs->trans("CustomersOrders").'</a>';
517 print '</td><td class="right">';
518 print $product->stats_commande['customers'];
519 print '</td><td class="right">';
520 print $product->stats_commande['nb'];
521 print '</td><td class="right">';
522 print price($product->stats_commande['qty'], 1, $langs, 0, 0);
523 print '</td>';
524 print '</tr>';
525 }
526 // Supplier orders
527 if ((isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight('fournisseur', 'commande', 'lire')) || (isModEnabled("supplier_order") && $user->hasRight('supplier_order', 'lire'))) {
528 $nblines++;
529 $ret = $product->load_stats_commande_fournisseur($socid);
530 if ($ret < 0) {
531 dol_print_error($db);
532 }
533 $langs->load("orders");
534 print '<tr><td>';
535 print '<a href="'.DOL_URL_ROOT.'/product/stats/commande_fournisseur.php?id='.$product->id.'">'.img_object('', 'supplier_order', 'class="pictofixedwidth"').$langs->trans("SuppliersOrders").'</a>';
536 print '</td><td class="right">';
537 print $product->stats_commande_fournisseur['suppliers'];
538 print '</td><td class="right">';
539 print $product->stats_commande_fournisseur['nb'];
540 print '</td><td class="right">';
541 print price($product->stats_commande_fournisseur['qty'], 1, $langs, 0, 0);
542 print '</td>';
543 print '</tr>';
544 }
545 // Customer invoices
546 if (isModEnabled('invoice') && $user->hasRight('facture', 'lire')) {
547 $nblines++;
548 $ret = $product->load_stats_facture($socid);
549 if ($ret < 0) {
550 dol_print_error($db);
551 }
552 $langs->load("bills");
553 print '<tr><td>';
554 print '<a href="'.DOL_URL_ROOT.'/product/stats/facture.php?id='.$product->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("CustomersInvoices").'</a>';
555 print '</td><td class="right">';
556 print $product->stats_facture['customers'];
557 print '</td><td class="right">';
558 print $product->stats_facture['nb'];
559 print '</td><td class="right">';
560 print price($product->stats_facture['qty'], 1, $langs, 0, 0);
561 print '</td>';
562 print '</tr>';
563 }
564 // Customer template invoices
565 if (isModEnabled("invoice") && $user->hasRight('facture', 'lire')) {
566 $nblines++;
567 $ret = $product->load_stats_facturerec($socid);
568 if ($ret < 0) {
569 dol_print_error($db);
570 }
571 $langs->load("bills");
572 print '<tr><td>';
573 print '<a href="'.DOL_URL_ROOT.'/product/stats/facturerec.php?id='.$product->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("RecurringInvoiceTemplate").'</a>';
574 print '</td><td class="right">';
575 print $product->stats_facture['customers'];
576 print '</td><td class="right">';
577 print $product->stats_facturerec['nb'];
578 print '</td><td class="right">';
579 print $product->stats_facturerec['qty'];
580 print '</td>';
581 print '</tr>';
582 }
583 // Supplier invoices
584 if ((isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight('fournisseur', 'facture', 'lire')) || (isModEnabled("supplier_invoice") && $user->hasRight('supplier_invoice', 'lire'))) {
585 $nblines++;
586 $ret = $product->load_stats_facture_fournisseur($socid);
587 if ($ret < 0) {
588 dol_print_error($db);
589 }
590 $langs->load("bills");
591 print '<tr><td>';
592 print '<a href="'.DOL_URL_ROOT.'/product/stats/facture_fournisseur.php?id='.$product->id.'">'.img_object('', 'supplier_invoice', 'class="pictofixedwidth"').$langs->trans("SuppliersInvoices").'</a>';
593 print '</td><td class="right">';
594 print $product->stats_facture_fournisseur['suppliers'];
595 print '</td><td class="right">';
596 print $product->stats_facture_fournisseur['nb'];
597 print '</td><td class="right">';
598 print price($product->stats_facture_fournisseur['qty'], 1, $langs, 0, 0);
599 print '</td>';
600 print '</tr>';
601 }
602
603 // Shipments
604 if (isModEnabled('shipping') && $user->hasRight('shipping', 'lire')) {
605 $nblines++;
606 $ret = $product->load_stats_sending($socid);
607 if ($ret < 0) {
608 dol_print_error($db);
609 }
610 $langs->load("sendings");
611 print '<tr><td>';
612 print '<a href="'.DOL_URL_ROOT.'/product/stats/expedition.php?id='.$product->id.'">'.img_object('', 'shipment', 'class="pictofixedwidth"').$langs->trans("Shipments").'</a>';
613 print '</td><td class="right">';
614 print $product->stats_expedition['customers'];
615 print '</td><td class="right">';
616 print $product->stats_expedition['nb'];
617 print '</td><td class="right">';
618 print $product->stats_expedition['qty'];
619 print '</td>';
620 print '</tr>';
621 }
622
623 // Receptions
624 if ((isModEnabled("reception") && $user->hasRight('reception', 'lire'))) {
625 $nblines++;
626 $ret = $product->load_stats_reception($socid);
627 if ($ret < 0) {
628 dol_print_error($db);
629 }
630 $langs->load("receptions");
631 print '<tr><td>';
632 print '<a href="'.DOL_URL_ROOT.'/product/stats/reception.php?id='.$product->id.'">'.img_object('', 'reception', 'class="pictofixedwidth"').$langs->trans("Receptions").'</a>';
633 print '</td><td class="right">';
634 print $product->stats_reception['suppliers'];
635 print '</td><td class="right">';
636 print $product->stats_reception['nb'];
637 print '</td><td class="right">';
638 print $product->stats_reception['qty'];
639 print '</td>';
640 print '</tr>';
641 }
642
643 // Contracts
644 if (isModEnabled('contract') && $user->hasRight('contrat', 'lire')) {
645 $nblines++;
646 $ret = $product->load_stats_contrat($socid);
647 if ($ret < 0) {
648 dol_print_error($db);
649 }
650 $langs->load("contracts");
651 print '<tr><td>';
652 print '<a href="'.DOL_URL_ROOT.'/product/stats/contrat.php?id='.$product->id.'">'.img_object('', 'contract', 'class="pictofixedwidth"').$langs->trans("Contracts").'</a>';
653 print '</td><td class="right">';
654 print $product->stats_contrat['customers'];
655 print '</td><td class="right">';
656 print $product->stats_contrat['nb'];
657 print '</td><td class="right">';
658 print price($product->stats_contrat['qty'], 1, $langs, 0, 0);
659 print '</td>';
660 print '</tr>';
661 }
662
663 // BOM
664 if (isModEnabled('bom') && $user->hasRight('bom', 'read')) {
665 $nblines++;
666 $ret = $product->load_stats_bom($socid);
667 if ($ret < 0) {
668 setEventMessage($product->error, 'errors');
669 }
670 $langs->load("mrp");
671
672 print '<tr><td>';
673 print '<a href="'.DOL_URL_ROOT.'/product/stats/bom.php?id='.$product->id.'">'.img_object('', 'bom', 'class="pictofixedwidth"').$langs->trans("BOM").'</a>';
674 print '</td><td class="right">';
675
676 print '</td><td class="right">';
677 print $form->textwithpicto($product->stats_bom['nb_toconsume'], $langs->trans("RowMaterial"));
678 print ' ';
679 print $form->textwithpicto($product->stats_bom['nb_toproduce'], $langs->trans("Finished"));
680 print '</td><td class="right">';
681 print $form->textwithpicto($product->stats_bom['qty_toconsume'], $langs->trans("RowMaterial"));
682 print ' ';
683 print $form->textwithpicto($product->stats_bom['qty_toproduce'], $langs->trans("Finished"));
684 print '</td>';
685 print '</tr>';
686 }
687
688 // MO
689 if (isModEnabled('mrp') && $user->hasRight('mrp', 'read')) {
690 $nblines++;
691 $ret = $product->load_stats_mo($socid);
692 if ($ret < 0) {
693 setEventMessages($product->error, $product->errors, 'errors');
694 }
695 $langs->load("mrp");
696 print '<tr><td>';
697 print '<a href="'.DOL_URL_ROOT.'/product/stats/mo.php?id='.$product->id.'">'.img_object('', 'mrp', 'class="pictofixedwidth"').$langs->trans("MO").'</a>';
698 print '</td><td class="right">';
699 print $form->textwithpicto($product->stats_mo['customers_toconsume'], $langs->trans("ToConsume"));
700 print ' ';
701 print $form->textwithpicto($product->stats_mo['customers_consumed'], $langs->trans("QtyAlreadyConsumed"));
702 print ' ';
703 print $form->textwithpicto($product->stats_mo['customers_toproduce'], $langs->trans("QtyToProduce"));
704 print ' ';
705 print $form->textwithpicto($product->stats_mo['customers_produced'], $langs->trans("QtyAlreadyProduced"));
706 print '</td><td class="right">';
707 print $form->textwithpicto($product->stats_mo['nb_toconsume'], $langs->trans("ToConsume"));
708 print ' ';
709 print $form->textwithpicto($product->stats_mo['nb_consumed'], $langs->trans("QtyAlreadyConsumed"));
710 print ' ';
711 print $form->textwithpicto($product->stats_mo['nb_toproduce'], $langs->trans("QtyToProduce"));
712 print ' ';
713 print $form->textwithpicto($product->stats_mo['nb_produced'], $langs->trans("QtyAlreadyProduced"));
714 print '</td><td class="right">';
715 print $form->textwithpicto($product->stats_mo['qty_toconsume'], $langs->trans("ToConsume"));
716 print ' ';
717 print $form->textwithpicto($product->stats_mo['qty_consumed'], $langs->trans("QtyAlreadyConsumed"));
718 print ' ';
719 print $form->textwithpicto($product->stats_mo['qty_toproduce'], $langs->trans("QtyToProduce"));
720 print ' ';
721 print $form->textwithpicto($product->stats_mo['qty_produced'], $langs->trans("QtyAlreadyProduced"));
722 print '</td>';
723 print '</tr>';
724 }
725 $parameters = array('socid' => $socid);
726 $reshook = $hookmanager->executeHooks('addMoreProductStat', $parameters, $product, $nblines); // Note that $action and $object may have been modified by some hooks
727 if ($reshook < 0) {
728 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
729 }
730
731 print $hookmanager->resPrint;
732
733
734 return $nblines++;
735}
736
744function show_stats_for_batch($batch, $socid)
745{
746 global $conf, $langs, $user, $db, $hookmanager;
747
748 $langs->LoadLangs(array('sendings', 'orders', 'receptions'));
749
750 $form = new Form($db);
751
752 $nblines = 0;
753
754 print '<tr class="liste_titre">';
755 print '<td class="left" width="25%">'.$langs->trans("Referers").'</td>';
756 print '<td class="right" width="25%">'.$langs->trans("NbOfThirdParties").'</td>';
757 print '<td class="right" width="25%">'.$langs->trans("NbOfObjectReferers").'</td>';
758 print '<td class="right" width="25%">'.$langs->trans("TotalQuantity").'</td>';
759 print '</tr>';
760
761 // Expeditions
762 if (isModEnabled('shipping') && $user->hasRight('expedition', 'lire')) {
763 $nblines++;
764 $ret = $batch->loadStatsExpedition($socid);
765 if ($ret < 0) {
766 dol_print_error($db);
767 }
768 $langs->load("bills");
769 print '<tr><td>';
770 print '<a href="'.dol_buildpath('/product/stock/stats/expedition.php', 1).'?id='.$batch->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("Shipments").'</a>';
771 print '</td><td class="right">';
772 print $batch->stats_expedition['customers'];
773 print '</td><td class="right">';
774 print $batch->stats_expedition['nb'];
775 print '</td><td class="right">';
776 print $batch->stats_expedition['qty'];
777 print '</td>';
778 print '</tr>';
779 }
780
781 if (isModEnabled("reception") && $user->hasRight('reception', 'lire')) {
782 $nblines++;
783 $ret = $batch->loadStatsReception($socid);
784 if ($ret < 0) {
785 dol_print_error($db);
786 }
787 $langs->load("bills");
788 print '<tr><td>';
789 print '<a href="'.dol_buildpath('/product/stock/stats/reception.php', 1).'?id='.$batch->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("Receptions").'</a>';
790 print '</td><td class="right">';
791 print $batch->stats_reception['customers'];
792 print '</td><td class="right">';
793 print $batch->stats_reception['nb'];
794 print '</td><td class="right">';
795 print $batch->stats_reception['qty'];
796 print '</td>';
797 print '</tr>';
798 } elseif (isModEnabled('supplier_order') && $user->hasRight('fournisseur', 'commande', 'lire')) {
799 $nblines++;
800 $ret = $batch->loadStatsSupplierOrder($socid);
801 if ($ret < 0) {
802 dol_print_error($db);
803 }
804 $langs->load("bills");
805 print '<tr><td>';
806 print '<a href="'.dol_buildpath('/product/stock/stats/commande_fournisseur.php', 1).'?id='.$batch->id.'">'.img_object('', 'bill', 'class="pictofixedwidth"').$langs->trans("SuppliersOrders").'</a>';
807 print '</td><td class="right">';
808 print $batch->stats_supplier_order['customers'];
809 print '</td><td class="right">';
810 print $batch->stats_supplier_order['nb'];
811 print '</td><td class="right">';
812 print $batch->stats_supplier_order['qty'];
813 print '</td>';
814 print '</tr>';
815 }
816
817 if (isModEnabled('mrp') && $user->hasRight('mrp', 'read')) {
818 $nblines++;
819 $ret = $batch->loadStatsMo($socid);
820 if ($ret < 0) {
821 dol_print_error($db);
822 }
823 $langs->load("mrp");
824 print '<tr><td>';
825 print '<a href="'.dol_buildpath('/product/stock/stats/mo.php', 1).'?id='.$batch->id.'">'.img_object('', 'mrp', 'class="pictofixedwidth"').$langs->trans("MO").'</a>';
826 print '</td><td class="right">';
827 // 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
828 print $form->textwithpicto($batch->stats_mo['customers_consumed'], $langs->trans("QtyAlreadyConsumed"));
829 // 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
830 print $form->textwithpicto($batch->stats_mo['customers_produced'], $langs->trans("QtyAlreadyProduced"));
831 print '</td><td class="right">';
832 // 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
833 print $form->textwithpicto($batch->stats_mo['nb_consumed'], $langs->trans("QtyAlreadyConsumed"));
834 // 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
835 print $form->textwithpicto($batch->stats_mo['nb_produced'], $langs->trans("QtyAlreadyProduced"));
836 print '</td><td class="right">';
837 // 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
838 print $form->textwithpicto($batch->stats_mo['qty_consumed'], $langs->trans("QtyAlreadyConsumed"));
839 // 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
840 print $form->textwithpicto($batch->stats_mo['qty_produced'], $langs->trans("QtyAlreadyProduced"));
841 print '</td>';
842 print '</tr>';
843 }
844
845 $parameters = array('socid' => $socid);
846 $reshook = $hookmanager->executeHooks('addMoreBatchProductStat', $parameters, $batch, $nblines); // Note that $action and $object may have been modified by some hooks
847 if ($reshook < 0) {
848 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
849 }
850
851 print $hookmanager->resPrint;
852
853
854 return $nblines++;
855}
856
869function measuring_units_string($unitscale = '', $measuring_style = '', $unitid = 0, $use_short_label = 0, $outputlangs = null)
870{
871 return measuringUnitString($unitid, $measuring_style, $unitscale, $use_short_label, $outputlangs);
872}
873
885function measuringUnitString($unitid, $measuring_style = '', $unitscale = '', $use_short_label = 0, $outputlangs = null)
886{
887 global $langs, $db;
888 global $measuring_unit_cache;
889
890 if (empty($outputlangs)) {
891 $outputlangs = $langs;
892 }
893
894 if (empty($measuring_unit_cache[$unitid.'_'.$measuring_style.'_'.$unitscale.'_'.$use_short_label])) {
895 require_once DOL_DOCUMENT_ROOT.'/core/class/cunits.class.php';
896 $measuringUnits = new CUnits($db);
897
898 if ($measuring_style == '' && $unitscale == '') {
899 $arrayforfilter = array(
900 't.rowid' => $unitid,
901 't.active' => 1
902 );
903 } elseif ($unitscale !== '') {
904 $arrayforfilter = array(
905 't.scale' => $unitscale,
906 't.unit_type' => $measuring_style,
907 't.active' => 1
908 );
909 } else {
910 $arrayforfilter = array(
911 't.rowid' => $unitid,
912 't.unit_type' => $measuring_style,
913 't.active' => 1
914 );
915 }
916 $result = $measuringUnits->fetchAll('', '', 0, 0, $arrayforfilter);
917
918 if ($result < 0) {
919 return -1;
920 } else {
921 if (is_array($measuringUnits->records) && count($measuringUnits->records) > 0) {
922 if ($use_short_label == 1) {
923 $labeltoreturn = $measuringUnits->records[key($measuringUnits->records)]->short_label;
924 } elseif ($use_short_label == 2) {
925 $labeltoreturn = $outputlangs->transnoentitiesnoconv(ucfirst($measuringUnits->records[key($measuringUnits->records)]->label).'Short');
926 } else {
927 $labeltoreturn = $outputlangs->transnoentitiesnoconv($measuringUnits->records[key($measuringUnits->records)]->label);
928 }
929 } else {
930 $labeltoreturn = '';
931 }
932 $measuring_unit_cache[$unitid.'_'.$measuring_style.'_'.$unitscale.'_'.$use_short_label] = $labeltoreturn;
933 return $labeltoreturn;
934 }
935 } else {
936 return $measuring_unit_cache[$unitid.'_'.$measuring_style.'_'.$unitscale.'_'.$use_short_label];
937 }
938}
939
947function measuring_units_squared($unitscale)
948{
949 $measuring_units = array();
950 $measuring_units[0] = 0; // m -> m3
951 $measuring_units[-1] = -2; // dm-> dm2
952 $measuring_units[-2] = -4; // cm -> cm2
953 $measuring_units[-3] = -6; // mm -> mm2
954 $measuring_units[98] = 98; // foot -> foot2
955 $measuring_units[99] = 99; // inch -> inch2
956 return $measuring_units[$unitscale];
957}
958
959
968{
969 $measuring_units = array();
970 $measuring_units[0] = 0; // m -> m2
971 $measuring_units[-1] = -3; // dm-> dm3
972 $measuring_units[-2] = -6; // cm -> cm3
973 $measuring_units[-3] = -9; // mm -> mm3
974 $measuring_units[98] = 88; // foot -> foot3
975 $measuring_units[99] = 89; // inch -> inch3
976 return $measuring_units[$unit];
977}
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
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
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_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode='add', $filterorigmodule='')
Complete or removed entries into a head array (used to build tabs).
getDolGlobalString($key, $default='')
Return 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.