dolibarr  13.0.2
card.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2020 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
5  * Copyright (C) 2005-2018 Regis Houssin <regis.houssin@inodbox.com>
6  * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
7  * Copyright (C) 2011-2014 Juanjo Menent <jmenent@2byte.es>
8  * Copyright (C) 2015 RaphaĆ«l Doursenaud <rdoursenaud@gpcsolutions.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <https://www.gnu.org/licenses/>.
22  */
23 
30 require '../../main.inc.php';
31 
32 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
33 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
35 
36 // Load translation files required by the page
37 $langs->loadLangs(array('bills', 'products', 'stocks'));
38 
39 $id = GETPOST('id', 'int');
40 $ref = GETPOST('ref', 'alpha');
41 $action = GETPOST('action', 'aZ09');
42 $confirm = GETPOST('confirm', 'alpha');
43 $cancel = GETPOST('cancel', 'alpha');
44 $key = GETPOST('key');
45 $parent = GETPOST('parent');
46 
47 // Security check
48 if (!empty($user->socid)) $socid = $user->socid;
49 $fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : ''));
50 $fieldtype = (!empty($ref) ? 'ref' : 'rowid');
51 $result = restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype);
52 
53 $object = new Product($db);
54 $objectid = 0;
55 if ($id > 0 || !empty($ref))
56 {
57  $result = $object->fetch($id, $ref);
58  $objectid = $object->id;
59  $id = $object->id;
60 }
61 
62 
63 /*
64  * Actions
65  */
66 
67 if ($cancel) $action = '';
68 
69 // Add subproduct to product
70 if ($action == 'add_prod' && ($user->rights->produit->creer || $user->rights->service->creer))
71 {
72  $error = 0;
73  $maxprod = GETPOST("max_prod", 'int');
74 
75  for ($i = 0; $i < $maxprod; $i++)
76  {
77  $qty = price2num(GETPOST("prod_qty_".$i, 'alpha'), 'MS');
78  if ($qty > 0)
79  {
80  if ($object->add_sousproduit($id, GETPOST("prod_id_".$i, 'int'), $qty, GETPOST("prod_incdec_".$i, 'int')) > 0)
81  {
82  //var_dump($i.' '.GETPOST("prod_id_".$i, 'int'), $qty, GETPOST("prod_incdec_".$i, 'int'));
83  $action = 'edit';
84  } else {
85  $error++;
86  $action = 're-edit';
87  if ($object->error == "isFatherOfThis") {
88  setEventMessages($langs->trans("ErrorAssociationIsFatherOfThis"), null, 'errors');
89  } else {
90  setEventMessages($object->error, $object->errors, 'errors');
91  }
92  }
93  } else {
94  if ($object->del_sousproduit($id, GETPOST("prod_id_".$i, 'int')) > 0)
95  {
96  $action = 'edit';
97  } else {
98  $error++;
99  $action = 're-edit';
100  setEventMessages($object->error, $object->errors, 'errors');
101  }
102  }
103  }
104 
105  if (!$error)
106  {
107  header("Location: ".$_SERVER["PHP_SELF"].'?id='.$object->id);
108  exit;
109  }
110 } elseif ($action === 'save_composed_product')
111 {
112  $TProduct = GETPOST('TProduct', 'array');
113  if (!empty($TProduct))
114  {
115  foreach ($TProduct as $id_product => $row)
116  {
117  if ($row['qty'] > 0) $object->update_sousproduit($id, $id_product, $row['qty'], isset($row['incdec']) ? 1 : 0);
118  else $object->del_sousproduit($id, $id_product);
119  }
120  setEventMessages('RecordSaved', null);
121  }
122  $action = '';
123 }
124 
125 
126 /*
127  * View
128  */
129 
130 $product_fourn = new ProductFournisseur($db);
131 $productstatic = new Product($db);
132 $form = new Form($db);
133 
134 // action recherche des produits par mot-cle et/ou par categorie
135 if ($action == 'search')
136 {
137  $current_lang = $langs->getDefaultLang();
138 
139  $sql = 'SELECT DISTINCT p.rowid, p.ref, p.label, p.fk_product_type as type, p.barcode, p.price, p.price_ttc, p.price_base_type, p.entity,';
140  $sql .= ' p.fk_product_type, p.tms as datem, p.tobatch';
141  if (!empty($conf->global->MAIN_MULTILANGS)) $sql .= ', pl.label as labelm, pl.description as descriptionm';
142  $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
143  $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_product as cp ON p.rowid = cp.fk_product';
144  if (!empty($conf->global->MAIN_MULTILANGS)) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_lang as pl ON pl.fk_product = p.rowid AND lang='".($current_lang)."'";
145  $sql .= ' WHERE p.entity IN ('.getEntity('product').')';
146  if ($key != "")
147  {
148  // For natural search
149  $params = array('p.ref', 'p.label', 'p.description', 'p.note');
150  // multilang
151  if (!empty($conf->global->MAIN_MULTILANGS))
152  {
153  $params[] = 'pl.label';
154  $params[] = 'pl.description';
155  $params[] = 'pl.note';
156  }
157  if (!empty($conf->barcode->enabled)) {
158  $params[] = 'p.barcode';
159  }
160  $sql .= natural_search($params, $key);
161  }
162  if (!empty($conf->categorie->enabled) && !empty($parent) && $parent != -1)
163  {
164  $sql .= " AND cp.fk_categorie ='".$db->escape($parent)."'";
165  }
166  $sql .= " ORDER BY p.ref ASC";
167 
168  $resql = $db->query($sql);
169 }
170 
171 $title = $langs->trans('ProductServiceCard');
172 $helpurl = '';
173 $shortlabel = dol_trunc($object->label, 16);
174 if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT))
175 {
176  $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('AssociatedProducts');
177  $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
178 }
179 if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE))
180 {
181  $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('AssociatedProducts');
182  $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
183 }
184 
185 llxHeader('', $title, $helpurl);
186 
187 $head = product_prepare_head($object);
188 $titre = $langs->trans("CardProduct".$object->type);
189 $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
190 print dol_get_fiche_head($head, 'subproduct', $titre, -1, $picto);
191 
192 
193 if ($id > 0 || !empty($ref))
194 {
195  /*
196  * Fiche en mode edition
197  */
198  if ($user->rights->produit->lire || $user->rights->service->lire)
199  {
200  $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
201 
202  $shownav = 1;
203  if ($user->socid && !in_array('product', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) $shownav = 0;
204 
205  dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref', '', '', '', 0, '', '', 0);
206 
207  if ($object->type != Product::TYPE_SERVICE || !empty($conf->global->STOCK_SUPPORTS_SERVICES) || empty($conf->global->PRODUIT_MULTIPRICES))
208  {
209  print '<div class="fichecenter">';
210  print '<div class="underbanner clearboth"></div>';
211 
212  print '<table class="border centpercent tableforfield">';
213 
214  // Nature
215  if ($object->type != Product::TYPE_SERVICE)
216  {
217  print '<tr><td class="titlefield">'.$langs->trans("Nature").'</td><td>';
218  print $object->getLibFinished();
219  print '</td></tr>';
220  }
221 
222  if (empty($conf->global->PRODUIT_MULTIPRICES))
223  {
224  // Price
225  print '<tr><td class="titlefield">'.$langs->trans("SellingPrice").'</td><td>';
226  if ($object->price_base_type == 'TTC')
227  {
228  print price($object->price_ttc).' '.$langs->trans($object->price_base_type);
229  } else {
230  print price($object->price).' '.$langs->trans($object->price_base_type ? $object->price_base_type : 'HT');
231  }
232  print '</td></tr>';
233 
234  // Price minimum
235  print '<tr><td>'.$langs->trans("MinPrice").'</td><td>';
236  if ($object->price_base_type == 'TTC')
237  {
238  print price($object->price_min_ttc).' '.$langs->trans($object->price_base_type);
239  } else {
240  print price($object->price_min).' '.$langs->trans($object->price_base_type ? $object->price_base_type : 'HT');
241  }
242  print '</td></tr>';
243  }
244 
245  print '</table>';
246  print '</div>';
247  }
248 
250 
251  print '<br>';
252 
253  $prodsfather = $object->getFather(); // Parent Products
254  $object->get_sousproduits_arbo(); // Load $object->sousprods
255  $prods_arbo = $object->get_arbo_each_prod();
256 
257  $nbofsubsubproducts = count($prods_arbo); // This include sub sub product into nb
258  $prodschild = $object->getChildsArbo($id, 1);
259  $nbofsubproducts = count($prodschild); // This include only first level of childs
260 
261 
262  print '<div class="fichecenter">';
263 
264  print load_fiche_titre($langs->trans("ProductParentList"), '', '');
265 
266  print '<table class="liste">';
267  print '<tr class="liste_titre">';
268  print '<td>'.$langs->trans('ParentProducts').'</td>';
269  print '<td>'.$langs->trans('Label').'</td>';
270  print '<td>'.$langs->trans('Qty').'</td>';
271  print '</td>';
272  if (count($prodsfather) > 0)
273  {
274  foreach ($prodsfather as $value)
275  {
276  $idprod = $value["id"];
277  $productstatic->id = $idprod; // $value["id"];
278  $productstatic->type = $value["fk_product_type"];
279  $productstatic->ref = $value['ref'];
280  $productstatic->label = $value['label'];
281  $productstatic->entity = $value['entity'];
282 
283  print '<tr class="oddeven">';
284  print '<td>'.$productstatic->getNomUrl(1, 'composition').'</td>';
285  print '<td>'.$productstatic->label.'</td>';
286  print '<td>'.$value['qty'].'</td>';
287  print '</tr>';
288  }
289  } else {
290  print '<tr class="oddeven">';
291  print '<td colspan="3" class="opacitymedium">'.$langs->trans("None").'</td>';
292  print '</tr>';
293  }
294  print '</table>';
295  print '</div>';
296 
297  print '<br>'."\n";
298 
299 
300  print '<div class="fichecenter">';
301 
302  $atleastonenotdefined = 0;
303  print load_fiche_titre($langs->trans("ProductAssociationList"), '', '');
304 
305  print '<form name="formComposedProduct" action="'.$_SERVER['PHP_SELF'].'" method="post">';
306  print '<input type="hidden" name="token" value="'.newToken().'" />';
307  print '<input type="hidden" name="action" value="save_composed_product" />';
308  print '<input type="hidden" name="id" value="'.$id.'" />';
309 
310  print '<table class="liste">';
311 
312  print '<tr class="liste_titre">';
313  print '<td>'.$langs->trans('ComposedProduct').'</td>';
314  print '<td>'.$langs->trans('Label').'</td>';
315  print '<td class="right" colspan="2">'.$langs->trans('MinSupplierPrice').'</td>';
316  print '<td class="right" colspan="2">'.$langs->trans('MinCustomerPrice').'</td>';
317  if (!empty($conf->stock->enabled)) print '<td class="right">'.$langs->trans('Stock').'</td>';
318  print '<td class="center">'.$langs->trans('Qty').'</td>';
319  print '<td class="center">'.$langs->trans('ComposedProductIncDecStock').'</td>';
320  print '</tr>'."\n";
321 
322  $totalsell = 0;
323  if (count($prods_arbo)) {
324  foreach ($prods_arbo as $value) {
325  $productstatic->fetch($value['id']);
326 
327  if ($value['level'] <= 1) {
328  print '<tr class="oddeven">';
329 
330  $notdefined = 0;
331  $nb_of_subproduct = $value['nb'];
332 
333  print '<td>'.$productstatic->getNomUrl(1, 'composition').'</td>';
334  print '<td>'.$productstatic->label.'</td>';
335 
336  // Best buying price
337  print '<td class="right">';
338  if ($product_fourn->find_min_price_product_fournisseur($productstatic->id) > 0)
339  {
340  print $langs->trans("BuyingPriceMinShort").': ';
341  if ($product_fourn->product_fourn_price_id > 0) print $product_fourn->display_price_product_fournisseur(0, 0);
342  else { print $langs->trans("NotDefined"); $notdefined++; $atleastonenotdefined++; }
343  }
344  print '</td>';
345 
346  // For avoid a non-numeric value
347  $fourn_unitprice = (!empty($product_fourn->fourn_unitprice) ? $product_fourn->fourn_unitprice : 0);
348  $fourn_remise_percent = (!empty($product_fourn->fourn_remise_percent) ? $product_fourn->fourn_remise_percent : 0);
349  $fourn_remise = (!empty($product_fourn->fourn_remise) ? $product_fourn->fourn_remise : 0);
350 
351  $unitline = price2num(($fourn_unitprice * (1 - ($fourn_remise_percent / 100)) - $fourn_remise), 'MU');
352  $totalline = price2num($value['nb'] * ($fourn_unitprice * (1 - ($fourn_remise_percent / 100)) - $fourn_remise), 'MT');
353  $total += $totalline;
354 
355  print '<td class="right">';
356  print ($notdefined ? '' : ($value['nb'] > 1 ? $value['nb'].'x' : '').price($unitline, '', '', 0, 0, -1, $conf->currency));
357  print '</td>';
358 
359  // Best selling price
360  $pricesell = $productstatic->price;
361  if (!empty($conf->global->PRODUIT_MULTIPRICES))
362  {
363  $pricesell = 'Variable';
364  } else {
365  $totallinesell = price2num($value['nb'] * ($pricesell), 'MT');
366  $totalsell += $totallinesell;
367  }
368  print '<td class="right" colspan="2">';
369  print ($notdefined ? '' : ($value['nb'] > 1 ? $value['nb'].'x' : ''));
370  if (is_numeric($pricesell)) print price($pricesell, '', '', 0, 0, -1, $conf->currency);
371  else print $langs->trans($pricesell);
372  print '</td>';
373 
374  // Stock
375  if (!empty($conf->stock->enabled)) print '<td class="right">'.$value['stock'].'</td>'; // Real stock
376 
377  // Qty + IncDec
378  if ($user->rights->produit->creer || $user->rights->service->creer)
379  {
380  print '<td class="center"><input type="text" value="'.$nb_of_subproduct.'" name="TProduct['.$productstatic->id.'][qty]" size="4" class="right" /></td>';
381  print '<td class="center"><input type="checkbox" name="TProduct['.$productstatic->id.'][incdec]" value="1" '.($value['incdec'] == 1 ? 'checked' : '').' /></td>';
382  } else {
383  print '<td>'.$nb_of_subproduct.'</td>';
384  print '<td>'.($value['incdec'] == 1 ? 'x' : '').'</td>';
385  }
386 
387  print '</tr>'."\n";
388  } else {
389  $hide = '';
390  if (empty($conf->global->PRODUCT_SHOW_SUB_SUB_PRODUCTS)) $hide = ' hideobject'; // By default, we do not show this. It makes screen very difficult to understand
391 
392  print '<tr class="oddeven'.$hide.'" id="sub-'.$value['id_parent'].'">';
393 
394  //$productstatic->ref=$value['label'];
395  $productstatic->ref = $value['ref'];
396  print '<td>';
397  for ($i = 0; $i < $value['level']; $i++) print ' &nbsp; &nbsp; '; // Add indentation
398  print $productstatic->getNomUrl(1, 'composition').'</td>';
399  print '<td>'.$productstatic->label.'</td>';
400 
401  // Best buying price
402  print '<td>&nbsp;</td>';
403  print '<td>&nbsp;</td>';
404  // Best selling price
405  print '<td>&nbsp;</td>';
406  print '<td>&nbsp;</td>';
407 
408  if (!empty($conf->stock->enabled)) print '<td></td>'; // Real stock
409  print '<td class="center">'.$value['nb'].'</td>';
410  print '<td>&nbsp;</td>';
411 
412  print '</tr>'."\n";
413  }
414  }
415 
416  print '<tr class="liste_total">';
417  print '<td class="liste_total"></td>';
418  print '<td class="liste_total"></td>';
419 
420  // Minimum buying price
421  print '<td class="liste_total right">';
422  print $langs->trans("TotalBuyingPriceMinShort");
423  print '</td>';
424 
425  print '<td class="liste_total right">';
426  if ($atleastonenotdefined) print $langs->trans("Unknown").' ('.$langs->trans("SomeSubProductHaveNoPrices").')';
427  print ($atleastonenotdefined ? '' : price($total, '', '', 0, 0, -1, $conf->currency));
428  print '</td>';
429 
430  // Minimum selling price
431  print '<td class="liste_total right">';
432  print $langs->trans("TotalSellingPriceMinShort");
433  print '</td>';
434 
435  print '<td class="liste_total right">';
436  if ($atleastonenotdefined) print $langs->trans("Unknown").' ('.$langs->trans("SomeSubProductHaveNoPrices").')';
437  print ($atleastonenotdefined ? '' : price($totalsell, '', '', 0, 0, -1, $conf->currency));
438  print '</td>';
439 
440  // Stock
441  if (!empty($conf->stock->enabled)) print '<td class="liste_total right">&nbsp;</td>';
442 
443  print '<td class="right" colspan="2">';
444  if ($user->rights->produit->creer || $user->rights->service->creer)
445  {
446  print '<input type="submit" class="button button-save" value="'.$langs->trans("Save").'">';
447  }
448  print '</td>';
449  print '</tr>'."\n";
450  } else {
451  $colspan = 8;
452  if (!empty($conf->stock->enabled)) $colspan++;
453 
454  print '<tr class="oddeven">';
455  print '<td colspan="'.$colspan.'" class="opacitymedium">'.$langs->trans("None").'</td>';
456  print '</tr>';
457  }
458 
459  print '</table>';
460 
461  /*if($user->rights->produit->creer || $user->rights->service->creer) {
462  print '<input type="submit" class="button button-save" value="'.$langs->trans("Save").'">';
463  }*/
464 
465  print '</form>';
466  print '</div>';
467 
468 
469 
470  // Form with product to add
471  if ((empty($action) || $action == 'view' || $action == 'edit' || $action == 'search' || $action == 're-edit') && ($user->rights->produit->creer || $user->rights->service->creer))
472  {
473  print '<br>';
474 
475  $rowspan = 1;
476  if (!empty($conf->categorie->enabled)) $rowspan++;
477 
478  print load_fiche_titre($langs->trans("ProductToAddSearch"), '', '');
479  print '<form action="'.DOL_URL_ROOT.'/product/composition/card.php?id='.$id.'" method="POST">';
480  print '<input type="hidden" name="action" value="search">';
481  print '<input type="hidden" name="id" value="'.$id.'">';
482  print '<div class="inline-block">';
483  print '<input type="hidden" name="token" value="'.newToken().'">';
484  print $langs->trans("KeywordFilter").': ';
485  print '<input type="text" name="key" value="'.$key.'"> &nbsp; ';
486  print '</div>';
487  if (!empty($conf->categorie->enabled))
488  {
489  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
490  print '<div class="inline-block">'.$langs->trans("CategoryFilter").': ';
491  print $form->select_all_categories(Categorie::TYPE_PRODUCT, $parent, 'parent').' &nbsp; </div>';
492  print ajax_combobox('parent');
493  }
494  print '<div class="inline-block">';
495  print '<input type="submit" class="button" value="'.$langs->trans("Search").'">';
496  print '</div>';
497  print '</form>';
498  }
499 
500 
501  // List of products
502  if ($action == 'search')
503  {
504  print '<br>';
505  print '<form action="'.DOL_URL_ROOT.'/product/composition/card.php?id='.$id.'" method="post">';
506  print '<input type="hidden" name="token" value="'.newToken().'">';
507  print '<input type="hidden" name="action" value="add_prod">';
508  print '<input type="hidden" name="id" value="'.$id.'">';
509  print '<table class="noborder centpercent">';
510  print '<tr class="liste_titre">';
511  print '<th class="liste_titre">'.$langs->trans("ComposedProduct").'</td>';
512  print '<th class="liste_titre">'.$langs->trans("Label").'</td>';
513  //print '<th class="liste_titre center">'.$langs->trans("IsInPackage").'</td>';
514  print '<th class="liste_titre right">'.$langs->trans("Qty").'</td>';
515  print '<th class="center">'.$langs->trans('ComposedProductIncDecStock').'</th>';
516  print '</tr>';
517  if ($resql)
518  {
519  $num = $db->num_rows($resql);
520  $i = 0;
521 
522  if ($num == 0) print '<tr><td colspan="4">'.$langs->trans("NoMatchFound").'</td></tr>';
523 
524  $MAX = 100;
525 
526  while ($i < min($num, $MAX))
527  {
528  $objp = $db->fetch_object($resql);
529  if ($objp->rowid != $id)
530  {
531  // check if a product is not already a parent product of this one
532  $prod_arbo = new Product($db);
533  $prod_arbo->id = $objp->rowid;
534  // This type is not supported (not required to have virtual products working).
535  if ($prod_arbo->type == Product::TYPE_ASSEMBLYKIT || $prod_arbo->type == Product::TYPE_STOCKKIT)
536  {
537  $is_pere = 0;
538  $prod_arbo->get_sousproduits_arbo();
539  // associations sousproduits
540  $prods_arbo = $prod_arbo->get_arbo_each_prod();
541  if (count($prods_arbo) > 0)
542  {
543  foreach ($prods_arbo as $key => $value)
544  {
545  if ($value[1] == $id)
546  {
547  $is_pere = 1;
548  }
549  }
550  }
551  if ($is_pere == 1)
552  {
553  $i++;
554  continue;
555  }
556  }
557 
558  print "\n";
559  print '<tr class="oddeven">';
560 
561  $productstatic->id = $objp->rowid;
562  $productstatic->ref = $objp->ref;
563  $productstatic->label = $objp->label;
564  $productstatic->type = $objp->type;
565  $productstatic->entity = $objp->entity;
566  $productstatic->status_batch = $objp->tobatch;
567 
568  print '<td>'.$productstatic->getNomUrl(1, '', 24).'</td>';
569  $labeltoshow = $objp->label;
570  if ($conf->global->MAIN_MULTILANGS && $objp->labelm) $labeltoshow = $objp->labelm;
571 
572  print '<td>'.$labeltoshow.'</td>';
573 
574 
575  if ($object->is_sousproduit($id, $objp->rowid))
576  {
577  //$addchecked = ' checked';
578  $qty = $object->is_sousproduit_qty;
579  $incdec = $object->is_sousproduit_incdec;
580  } else {
581  //$addchecked = '';
582  $qty = 0;
583  $incdec = 0;
584  }
585  // Contained into package
586  /*print '<td class="center"><input type="hidden" name="prod_id_'.$i.'" value="'.$objp->rowid.'">';
587  print '<input type="checkbox" '.$addchecked.'name="prod_id_chk'.$i.'" value="'.$objp->rowid.'"></td>';*/
588  // Qty
589  print '<td class="right"><input type="hidden" name="prod_id_'.$i.'" value="'.$objp->rowid.'"><input type="text" size="2" name="prod_qty_'.$i.'" value="'.($qty ? $qty : '').'"></td>';
590 
591  // Inc Dec
592  print '<td class="center">';
593  if ($qty) print '<input type="checkbox" name="prod_incdec_'.$i.'" value="1" '.($incdec ? 'checked' : '').'>';
594  else {
595  // TODO Hide field and show it when setting a qty
596  print '<input type="checkbox" name="prod_incdec_'.$i.'" value="1" checked>';
597  //print '<input type="checkbox" disabled name="prod_incdec_'.$i.'" value="1" checked>';
598  }
599  print '</td>';
600 
601  print '</tr>';
602  }
603  $i++;
604  }
605  if ($num > $MAX) {
606  print '<tr class="oddeven">';
607  print '<td><span class="opacitymedium">'.$langs->trans("More").'...</span></td>';
608  print '<td></td>';
609  print '<td></td>';
610  print '<td></td>';
611  print '</tr>';
612  }
613  } else {
614  dol_print_error($db);
615  }
616  print '</table>';
617  print '<input type="hidden" name="max_prod" value="'.$i.'">';
618 
619  if ($num > 0)
620  {
621  print '<br><div class="center">';
622  print '<input type="submit" class="button" name="save" value="'.$langs->trans("Add").'/'.$langs->trans("Update").'">';
623  print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
624  print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
625  print '</div>';
626  }
627 
628  print '</form>';
629  }
630  }
631 }
632 
633 // End of page
634 llxFooter();
635 $db->close();
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Class to manage products or services.
const TYPE_ASSEMBLYKIT
Advanced feature: assembly kit.
const TYPE_STOCKKIT
Advanced feature: stock kit.
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete= 'resolve')
Convert a html select field into an ajax combobox.
Definition: ajax.lib.php:391
const TYPE_SERVICE
Service.
const TYPE_PRODUCT
Regular product.
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...
llxHeader()
Empty header.
Definition: wrapper.php:45
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
Class to manage generation of HTML components Only common components must be here.
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=0)
Check permissions of a user to show a page and an object.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
print $_SERVER["PHP_SELF"]
Edit parameters.
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
print
Draft customers invoices.
Definition: index.php:89
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_trunc($string, $size=40, $trunc= 'right', $stringencoding= 'UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding &#39;...&#39; if string larger than length.
dol_banner_tab($object, $paramid, $morehtml= '', $shownav=1, $fieldid= 'rowid', $fieldref= 'ref', $morehtmlref= '', $moreparam= '', $nodbprefix=0, $morehtmlleft= '', $morehtmlstatus= '', $onlybanner=0, $morehtmlright= '')
Show tab footer of a card.
llxFooter()
Empty footer.
Definition: wrapper.php:59
Class to manage predefined suppliers products.
product_prepare_head($object)
Prepare array with list of tabs.
Definition: product.lib.php:35