dolibarr  17.0.4
fournisseurs.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2021 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
5  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
6  * Copyright (C) 2010-2012 Juanjo Menent <jmenent@2byte.es>
7  * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
8  * Copyright (C) 2014 Ion Agorria <ion@agorria.com>
9  * Copyright (C) 2015 Alexandre Spangaro <aspangaro@open-dsi.fr>
10  * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
11  * Copyright (C) 2019 Frédéric France <frederic.france@netlogic.fr>
12  * Copyright (C) 2019 Tim Otte <otte@meuser.it>
13  * Copyright (C) 2020 Pierre Ardoin <mapiolca@me.com>
14  * Copyright (C) 2023 Joachim Kueter <git-jk@bloxera.com>
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program. If not, see <https://www.gnu.org/licenses/>.
28  */
29 
36 // Load Dolibarr environment
37 require '../main.inc.php';
38 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
39 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
40 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
41 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
42 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
43 require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_expression.class.php';
44 require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
45 if (isModEnabled('barcode')) {
46  dol_include_once('/core/class/html.formbarcode.class.php');
47 }
48 // Load translation files required by the page
49 $langs->loadLangs(array('products', 'suppliers', 'bills', 'margins', 'stocks'));
50 
51 $id = GETPOST('id', 'int');
52 $ref = GETPOST('ref', 'alpha');
53 $rowid = GETPOST('rowid', 'int');
54 $action = GETPOST('action', 'aZ09');
55 $cancel = GETPOST('cancel', 'alpha');
56 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'pricesuppliercard';
57 
58 $socid = GETPOST('socid', 'int');
59 $cost_price = price2num(GETPOST('cost_price', 'alpha'), '', 2);
60 $pmp = price2num(GETPOST('pmp', 'alpha'), '', 2);
61 
62 $backtopage = GETPOST('backtopage', 'alpha');
63 $error = 0;
64 
65 $extrafields = new ExtraFields($db);
66 
67 // If socid provided by ajax company selector
68 if (GETPOST('search_fourn_id', 'int')) {
69  $_GET['id_fourn'] = GETPOST('search_fourn_id', 'int');
70  $_POST['id_fourn'] = GETPOST('search_fourn_id', 'int');
71 }
72 
73 // Security check
74 $fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : ''));
75 $fieldtype = (!empty($ref) ? 'ref' : 'rowid');
76 if ($user->socid) {
77  $socid = $user->socid;
78 }
79 
80 if (empty($user->rights->fournisseur->lire) && (empty($conf->margin->enabled) && !$user->hasRight("margin", "liretous"))) {
82 }
83 
84 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
85 $sortfield = GETPOST('sortfield', 'aZ09comma');
86 $sortorder = GETPOST('sortorder', 'aZ09comma');
87 $page = (GETPOST("page", 'int') ?GETPOST("page", 'int') : 0);
88 if (empty($page) || $page == -1) {
89  $page = 0;
90 } // If $page is not defined, or '' or -1
91 $offset = $limit * $page;
92 $pageprev = $page - 1;
93 $pagenext = $page + 1;
94 if (!$sortfield) {
95  $sortfield = "s.nom";
96 }
97 if (!$sortorder) {
98  $sortorder = "ASC";
99 }
100 
101 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
102 $hookmanager->initHooks(array('pricesuppliercard', 'globalcard'));
103 
104 $object = new ProductFournisseur($db);
105 if ($id > 0 || $ref) {
106  $object->fetch($id, $ref);
107 }
108 
109 $usercanread = (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->lire) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->lire));
110 $usercancreate = (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->creer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->creer));
111 
112 if ($object->id > 0) {
113  if ($object->type == $object::TYPE_PRODUCT) {
114  restrictedArea($user, 'produit', $object->id, 'product&product', '', '');
115  }
116  if ($object->type == $object::TYPE_SERVICE) {
117  restrictedArea($user, 'service', $object->id, 'product&product', '', '');
118  }
119 } else {
120  restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype);
121 }
122 
123 
124 /*
125  * Actions
126  */
127 
128 if ($cancel) {
129  $action = '';
130 }
131 
132 $parameters = array('socid'=>$socid, 'id_prod'=>$id);
133 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
134 if ($reshook < 0) {
135  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
136 }
137 
138 if (empty($reshook)) {
139  if ($action == 'setcost_price') {
140  if ($id) {
141  $result = $object->fetch($id);
142  $object->cost_price = price2num($cost_price);
143  $result = $object->update($object->id, $user);
144  if ($result > 0) {
145  setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
146  $action = '';
147  } else {
148  $error++;
149  setEventMessages($object->error, $object->errors, 'errors');
150  }
151  }
152  }
153  if ($action == 'setpmp') {
154  if ($id) {
155  $result = $object->fetch($id);
156  $object->pmp = price2num($pmp);
157  $sql = "UPDATE ".MAIN_DB_PREFIX."product SET pmp = ".((float) $object->pmp)." WHERE rowid = ".((int) $id);
158  $resql = $db->query($sql);
159  //$result = $object->update($object->id, $user);
160  if ($resql) {
161  setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
162  $action = '';
163  } else {
164  $error++;
165  setEventMessages($object->error, $object->errors, 'errors');
166  }
167  }
168  }
169 
170  if ($action == 'confirm_remove_pf') {
171  if ($rowid) { // id of product supplier price to remove
172  $action = '';
173  $result = $object->remove_product_fournisseur_price($rowid);
174  if ($result > 0) {
175  $db->query("DELETE FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields WHERE fk_object = ".((int) $rowid));
176  setEventMessages($langs->trans("PriceRemoved"), null, 'mesgs');
177  } else {
178  $error++;
179  setEventMessages($object->error, $object->errors, 'errors');
180  }
181  }
182  }
183 
184  if ($action == 'save_price') {
185  $ref_fourn_price_id = GETPOSTINT('ref_fourn_price_id');
186  $id_fourn = GETPOST("id_fourn");
187  if (empty($id_fourn)) {
188  $id_fourn = GETPOST("search_id_fourn");
189  }
190  $ref_fourn = GETPOST("ref_fourn");
191  if (empty($ref_fourn)) {
192  $ref_fourn = GETPOST("search_ref_fourn");
193  }
194  $ref_fourn_old = GETPOST("ref_fourn_old");
195  if (empty($ref_fourn_old)) {
196  $ref_fourn_old = $ref_fourn;
197  }
198  $quantity = price2num(GETPOST("qty", 'alphanohtml'), 'MS');
199  $remise_percent = price2num(GETPOST('remise_percent', 'alpha'));
200 
201  $npr = preg_match('/\*/', GETPOST('tva_tx', 'alpha')) ? 1 : 0;
202  $tva_tx = str_replace('*', '', GETPOST('tva_tx', 'alpha'));
203  if (!preg_match('/\‍((.*)\‍)/', $tva_tx)) {
204  $tva_tx = price2num($tva_tx);
205  }
206 
207  $price_expression = GETPOST('eid', 'int') ? GETPOST('eid', 'int') : ''; // Discard expression if not in expression mode
208  $delivery_time_days = GETPOST('delivery_time_days', 'int') ? GETPOST('delivery_time_days', 'int') : '';
209  $supplier_reputation = GETPOST('supplier_reputation');
210  $supplier_description = GETPOST('supplier_description', 'restricthtml');
211  $barcode = GETPOST('barcode', 'alpha');
212  $fk_barcode_type = GETPOST('fk_barcode_type', 'int');
213  $packaging = price2num(GETPOST("packaging", 'alphanohtml'), 'MS');
214 
215  if ($tva_tx == '') {
216  $error++;
217  $langs->load("errors");
218  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("VATRateForSupplierProduct")), null, 'errors');
219  }
220  if (!is_numeric($tva_tx)) {
221  $error++;
222  $langs->load("errors");
223  setEventMessages($langs->trans("ErrorFieldMustBeANumeric", $langs->transnoentities("VATRateForSupplierProduct")), null, 'errors');
224  }
225  if (empty($quantity)) {
226  $error++;
227  $langs->load("errors");
228  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Qty")), null, 'errors');
229  }
230  if (empty($ref_fourn)) {
231  $error++;
232  $langs->load("errors");
233  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("RefSupplier")), null, 'errors');
234  }
235  if ($id_fourn <= 0) {
236  $error++;
237  $langs->load("errors");
238  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Supplier")), null, 'errors');
239  }
240  if (price2num(GETPOST("price")) < 0 || GETPOST("price") == '') {
241  if ($price_expression === '') { // Return error of missing price only if price_expression not set
242  $error++;
243  $langs->load("errors");
244  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Price")), null, 'errors');
245  } else {
246  $_POST["price"] = 0;
247  }
248  }
249  if (isModEnabled("multicurrency")) {
250  if (!GETPOST("multicurrency_code")) {
251  $error++;
252  $langs->load("errors");
253  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Currency")), null, 'errors');
254  }
255  if (price2num(GETPOST("multicurrency_tx")) <= 0 || GETPOST("multicurrency_tx") == '') {
256  $error++;
257  $langs->load("errors");
258  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("CurrencyRate")), null, 'errors');
259  }
260  if (price2num(GETPOST("multicurrency_price")) < 0 || GETPOST("multicurrency_price") == '') {
261  $error++;
262  $langs->load("errors");
263  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("PriceCurrency")), null, 'errors');
264  }
265  }
266 
267  if (!$error) {
268  $db->begin();
269 
270  if (empty($ref_fourn_price_id)) {
271  $ret = $object->add_fournisseur($user, $id_fourn, $ref_fourn_old, $quantity); // This insert record with no value for price. Values are update later with update_buyprice
272  if ($ret == -3) {
273  $error++;
274 
275  $tmpobject = new Product($db);
276  $tmpobject->fetch($object->product_id_already_linked);
277  $productLink = $tmpobject->getNomUrl(1, 'supplier');
278 
279  $texttoshow = $langs->trans("ReferenceSupplierIsAlreadyAssociatedWithAProduct", '{s1}');
280  $texttoshow = str_replace('{s1}', $productLink, $texttoshow);
281  setEventMessages($texttoshow, null, 'errors');
282  } elseif ($ret < 0) {
283  $error++;
284  setEventMessages($object->error, $object->errors, 'errors');
285  }
286  }
287 
288  if (!$error) {
289  $supplier = new Fournisseur($db);
290  $result = $supplier->fetch($id_fourn);
291  if ($ref_fourn_price_id > 0) {
292  $object->fetch_product_fournisseur_price($ref_fourn_price_id);
293  }
294  $extralabels = $extrafields->fetch_name_optionals_label("product_fournisseur_price");
295  $extrafield_values = $extrafields->getOptionalsFromPost("product_fournisseur_price");
296 
297  $newprice = price2num(GETPOST("price", "alpha"));
298 
299  if (empty($packaging)) {
300  $packaging = 1;
301  }
302  /* We can have a puchase ref that need to buy 100 min for a given price and with a packaging of 50.
303  if ($packaging < $quantity) {
304  $packaging = $quantity;
305  }*/
306  $object->packaging = $packaging;
307 
308  if (isModEnabled("multicurrency")) {
309  $multicurrency_tx = price2num(GETPOST("multicurrency_tx", 'alpha'));
310  $multicurrency_price = price2num(GETPOST("multicurrency_price", 'alpha'));
311  $multicurrency_code = GETPOST("multicurrency_code", 'alpha');
312 
313  $ret = $object->update_buyprice($quantity, $newprice, $user, GETPOST("price_base_type"), $supplier, GETPOST("oselDispo"), $ref_fourn, $tva_tx, GETPOST("charges"), $remise_percent, 0, $npr, $delivery_time_days, $supplier_reputation, array(), '', $multicurrency_price, GETPOST("multicurrency_price_base_type"), $multicurrency_tx, $multicurrency_code, $supplier_description, $barcode, $fk_barcode_type, $extrafield_values);
314  } else {
315  $ret = $object->update_buyprice($quantity, $newprice, $user, GETPOST("price_base_type"), $supplier, GETPOST("oselDispo"), $ref_fourn, $tva_tx, GETPOST("charges"), $remise_percent, 0, $npr, $delivery_time_days, $supplier_reputation, array(), '', 0, 'HT', 1, '', $supplier_description, $barcode, $fk_barcode_type, $extrafield_values);
316  }
317  if ($ret < 0) {
318  $error++;
319  setEventMessages($object->error, $object->errors, 'errors');
320  } else {
321  if (isModEnabled('dynamicprices') && $price_expression !== '') {
322  //Check the expression validity by parsing it
323  require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
324  $priceparser = new PriceParser($db);
325  $object->fk_supplier_price_expression = $price_expression;
326  $price_result = $priceparser->parseProductSupplier($object);
327  if ($price_result < 0) { //Expression is not valid
328  $error++;
329  setEventMessages($priceparser->translatedError(), null, 'errors');
330  }
331  }
332  if (!$error && isModEnabled('dynamicprices')) {
333  //Set the price expression for this supplier price
334  $ret = $object->setSupplierPriceExpression($price_expression);
335  if ($ret < 0) {
336  $error++;
337  setEventMessages($object->error, $object->errors, 'errors');
338  }
339  }
340  }
341  }
342 
343  if (!$error) {
344  $db->commit();
345  $action = '';
346  } else {
347  $db->rollback();
348  }
349  } else {
350  $action = 'add_price';
351  }
352  }
353 }
354 
355 
356 /*
357  * view
358  */
359 
360 $form = new Form($db);
361 
362 $title = $langs->trans('ProductServiceCard');
363 $helpurl = '';
364 $shortlabel = dol_trunc($object->label, 16);
365 if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) {
366  $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('BuyingPrices');
367  $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos|DE:Modul_Produkte';
368 }
369 if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) {
370  $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('BuyingPrices');
371  $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios|DE:Modul_Lesitungen';
372 }
373 
374 llxHeader('', $title, $helpurl, '', 0, 0, '', '', '', 'classforhorizontalscrolloftabs');
375 
376 if ($id > 0 || $ref) {
377  if ($result) {
378  if ($action == 'ask_remove_pf') {
379  $form = new Form($db);
380  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$id.'&rowid='.$rowid, $langs->trans('DeleteProductBuyPrice'), $langs->trans('ConfirmDeleteProductBuyPrice'), 'confirm_remove_pf', '', 0, 1);
381  echo $formconfirm;
382  }
383 
384  if ($action != 'edit' && $action != 're-edit') {
385  $head = product_prepare_head($object);
386  $titre = $langs->trans("CardProduct".$object->type);
387  $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
388 
389  print dol_get_fiche_head($head, 'suppliers', $titre, -1, $picto);
390 
391  $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
392  $object->next_prev_filter = " fk_product_type = ".$object->type;
393 
394  $shownav = 1;
395  if ($user->socid && !in_array('product', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) {
396  $shownav = 0;
397  }
398 
399  dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
400 
401  print '<div class="fichecenter">';
402 
403  print '<div class="underbanner clearboth"></div>';
404  print '<table class="border tableforfield centpercent">';
405 
406  // Type
407  if (isModEnabled("product") && isModEnabled("service")) {
408  $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service");
409  print '<tr><td class="">';
410  print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type');
411  print '</td><td>';
412  print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat);
413  print '</td></tr>';
414  }
415 
416  // Cost price. Can be used for margin module for option "calculate margin on explicit cost price
417  print '<tr><td>';
418  $textdesc = $langs->trans("CostPriceDescription");
419  $textdesc .= "<br>".$langs->trans("CostPriceUsage");
420  $text = $form->textwithpicto($langs->trans("CostPrice"), $textdesc, 1, 'help', '');
421  print $form->editfieldkey($text, 'cost_price', $object->cost_price, $object, $usercancreate, 'amount:6');
422  print '</td><td>';
423  print $form->editfieldval($text, 'cost_price', $object->cost_price, $object, $usercancreate, 'amount:6');
424  print '</td></tr>';
425 
426  // PMP
427  $usercaneditpmp = 0;
428  if (!empty($conf->global->PRODUCT_CAN_EDIT_WAP)) {
429  $usercaneditpmp = $usercancreate;
430  }
431  print '<tr><td class="titlefieldcreate">';
432  $textdesc = $langs->trans("AverageUnitPricePMPDesc");
433  $text = $form->textwithpicto($langs->trans("AverageUnitPricePMPShort"), $textdesc, 1, 'help', '');
434  print $form->editfieldkey($text, 'pmp', $object->pmp, $object, $usercaneditpmp, 'amount:6');
435  print '</td><td>';
436  print $form->editfieldval($text, 'pmp', ($object->pmp > 0 ? $object->pmp : ''), $object, $usercaneditpmp, 'amount:6');
437  if ($object->pmp > 0) {
438  print ' '.$langs->trans("HT");
439  }
440  /*
441  .$form->textwithpicto($langs->trans("AverageUnitPricePMPShort"), $langs->trans("AverageUnitPricePMPDesc")).'</td>';
442  print '<td>';
443  if ($object->pmp > 0) {
444  print price($object->pmp).' '.$langs->trans("HT");
445  }*/
446  print '</td>';
447  print '</tr>';
448 
449  // Best buying Price
450  print '<tr><td class="titlefieldcreate">'.$langs->trans("BuyingPriceMin").'</td>';
451  print '<td>';
452  $product_fourn = new ProductFournisseur($db);
453  if ($product_fourn->find_min_price_product_fournisseur($object->id) > 0) {
454  if ($product_fourn->product_fourn_price_id > 0) {
455  print $product_fourn->display_price_product_fournisseur();
456  } else {
457  print $langs->trans("NotDefined");
458  }
459  }
460  print '</td></tr>';
461 
462  print '</table>';
463 
464  print '</div>';
465  print '<div style="clear:both"></div>';
466 
467  print dol_get_fiche_end();
468 
469 
470  // Form to add or update a price
471  if (($action == 'add_price' || $action == 'update_price') && $usercancreate) {
472  $langs->load("suppliers");
473 
474  print "<!-- form to add a supplier price -->\n";
475  print '<br>';
476 
477  if ($rowid) {
478  $object->fetch_product_fournisseur_price($rowid, 1); //Ignore the math expression when getting the price
479  print load_fiche_titre($langs->trans("ChangeSupplierPrice"));
480  } else {
481  print load_fiche_titre($langs->trans("AddSupplierPrice"));
482  }
483 
484  print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="POST">';
485  print '<input type="hidden" name="token" value="'.newToken().'">';
486  print '<input type="hidden" name="action" value="save_price">';
487 
488  print dol_get_fiche_head();
489 
490  print '<table class="border centpercent">';
491 
492  // Supplier
493  print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Supplier").'</td><td>';
494  if ($rowid) {
495  $supplier = new Fournisseur($db);
496  $supplier->fetch($socid);
497  print $supplier->getNomUrl(1);
498  print '<input type="hidden" name="id_fourn" value="'.$socid.'">';
499  print '<input type="hidden" name="ref_fourn_price_id" value="'.$rowid.'">';
500  print '<input type="hidden" name="rowid" value="'.$rowid.'">';
501  print '<input type="hidden" name="socid" value="'.$socid.'">';
502  } else {
503  $events = array();
504  $events[] = array('method' => 'getVatRates', 'url' => dol_buildpath('/core/ajax/vatrates.php', 1), 'htmlname' => 'tva_tx', 'params' => array());
505  print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(GETPOST("id_fourn", 'alpha'), 'id_fourn', 'fournisseur=1', 'SelectThirdParty', 0, 0, $events);
506 
507  $parameters = array('filtre'=>"fournisseur=1", 'html_name'=>'id_fourn', 'selected'=>GETPOST("id_fourn"), 'showempty'=>1, 'prod_id'=>$object->id);
508  $reshook = $hookmanager->executeHooks('formCreateThirdpartyOptions', $parameters, $object, $action);
509  if (empty($reshook)) {
510  if (empty($form->result)) {
511  print '<a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&type=f&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id.'&action='.$action).'">';
512  print img_picto($langs->trans("CreateDolibarrThirdPartySupplier"), 'add', 'class="marginleftonly"');
513  print '</a>';
514  }
515  }
516  print '<script type="text/javascript">
517  $(document).ready(function () {
518  $("#search_id_fourn").change(load_vat)
519  console.log("Requesting default VAT rate for the supplier...")
520  });
521  function load_vat() {
522  // get soc id
523  let socid = $("#id_fourn")[0].value
524 
525  // load available VAT rates
526  let vat_url = "'.dol_buildpath('/core/ajax/vatrates.php', 1).'"
527  //Make GET request with params
528  let options = "";
529  options += "id=" + socid
530  options += "&htmlname=tva_tx"
531  options += "&action=default" // not defined in vatrates.php, default behavior.
532 
533  var get = $.getJSON(
534  vat_url,
535  options,
536  (data) => {
537  rate_options = $.parseHTML(data.value)
538  rate_options.forEach(opt => {
539  if (opt.selected) {
540  replaceVATWithSupplierValue(opt.value)
541  return
542  }
543  })
544  }
545  );
546 
547  }
548  function replaceVATWithSupplierValue(vat_rate) {
549  console.log("Default VAT rate for the supplier: " + vat_rate + "%")
550  $("[name=\'tva_tx\']")[0].value = vat_rate;
551  }
552  </script>';
553  }
554  print '</td></tr>';
555 
556  // Ref supplier
557  print '<tr><td class="fieldrequired">'.$langs->trans("SupplierRef").'</td><td>';
558  if ($rowid) {
559  print '<input type="hidden" name="ref_fourn_old" value="'.$object->ref_supplier.'">';
560  print '<input class="flat width150" maxlength="128" name="ref_fourn" value="'.$object->ref_supplier.'">';
561  } else {
562  print '<input class="flat width150" maxlength="128" name="ref_fourn" value="'.(GETPOST("ref_fourn") ? GETPOST("ref_fourn") : '').'">';
563  }
564  print '</td>';
565  print '</tr>';
566 
567  // Availability
568  if (getDolGlobalInt('FOURN_PRODUCT_AVAILABILITY')) {
569  $langs->load("propal");
570  print '<tr><td>'.$langs->trans("Availability").'</td><td>';
571  $form->selectAvailabilityDelay($object->fk_availability, "oselDispo", 1);
572  print '</td></tr>'."\n";
573  }
574 
575  // Qty min
576  print '<tr>';
577  print '<td class="fieldrequired">'.$langs->trans("QtyMin").'</td>';
578  print '<td>';
579  $quantity = GETPOSTISSET('qty') ? price2num(GETPOST('qty', 'alphanohtml'), 'MS') : "1";
580  if ($rowid) {
581  print '<input type="hidden" name="qty" value="'.$object->fourn_qty.'">';
582  print $object->fourn_qty;
583  } else {
584  print '<input class="flat" name="qty" size="5" value="'.$quantity.'">';
585  }
586  // Units
587  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
588  $unit = $object->getLabelOfUnit();
589  if ($unit !== '') {
590  print '&nbsp;&nbsp;'.$langs->trans($unit);
591  }
592  }
593  print '</td></tr>';
594 
595  if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
596  // Packaging/Conditionnement
597  print '<tr>';
598 
599  print '<td class="fieldrequired">'.$form->textwithpicto($langs->trans("PackagingForThisProduct"), $langs->trans("PackagingForThisProductDesc")).'</td>';
600  print '<td>';
601  $packaging = GETPOSTISSET('packaging') ? price2num(GETPOST('packaging', 'alphanohtml'), 'MS') : ((empty($rowid)) ? "1" : price2num($object->packaging, 'MS'));
602  print '<input class="flat" name="packaging" size="5" value="'.$packaging.'">';
603 
604  // Units
605  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
606  $unit = $object->getLabelOfUnit();
607  if ($unit !== '') {
608  print '&nbsp;&nbsp;'.$langs->trans($unit);
609  }
610  }
611  }
612  // Vat rate
613  $default_vat = '';
614 
615  // We don't have supplier, so we try to guess.
616  // For this we build a fictive supplier with same properties than user but using vat)
617  $mysoc2 = clone $mysoc;
618  $mysoc2->name = 'Fictive seller with same country';
619  $mysoc2->tva_assuj = 1;
620  $default_vat = get_default_tva($mysoc2, $mysoc, $object->id, 0);
621  $default_npr = get_default_npr($mysoc2, $mysoc, $object->id, 0);
622  if (empty($default_vat)) {
623  $default_npr = $default_vat;
624  }
625 
626  print '<tr><td class="fieldrequired">'.$langs->trans("VATRateForSupplierProduct").'</td>';
627  print '<td>';
628  //print $form->load_tva('tva_tx',$object->tva_tx,$supplier,$mysoc); // Do not use list here as it may be any vat rates for any country
629  if (!empty($rowid)) { // If we have a supplier, it is an update, we must show the vat of current supplier price
630  $tmpproductsupplier = new ProductFournisseur($db);
631  $tmpproductsupplier->fetch_product_fournisseur_price($rowid, 1);
632  $default_vat = $tmpproductsupplier->fourn_tva_tx;
633  $default_npr = $tmpproductsupplier->fourn_tva_npr;
634  } else {
635  if (empty($default_vat)) {
636  $default_vat = $object->tva_tx;
637  }
638  }
639  $vattosuggest = (GETPOSTISSET("tva_tx") ? vatrate(GETPOST("tva_tx")) : ($default_vat != '' ?vatrate($default_vat) : ''));
640  $vattosuggest = preg_replace('/\s*\‍(.*\‍)$/', '', $vattosuggest);
641  print '<input type="text" class="flat" size="5" name="tva_tx" value="'.$vattosuggest.'">';
642  print '</td></tr>';
643 
644  if (isModEnabled('dynamicprices')) { //Only show price mode and expression selector if module is enabled
645  // Price mode selector
646  print '<tr><td class="fieldrequired">'.$langs->trans("PriceMode").'</td><td>';
647  $price_expression = new PriceExpression($db);
648  $price_expression_list = array(0 => $langs->trans("PriceNumeric")); //Put the numeric mode as first option
649  foreach ($price_expression->list_price_expression() as $entry) {
650  $price_expression_list[$entry->id] = $entry->title;
651  }
652  $price_expression_preselection = GETPOST('eid') ? GETPOST('eid') : ($object->fk_supplier_price_expression ? $object->fk_supplier_price_expression : '0');
653  print $form->selectarray('eid', $price_expression_list, $price_expression_preselection);
654  print '&nbsp; <div id="expression_editor" class="button">'.$langs->trans("PriceExpressionEditor").'</div>';
655  print '</td></tr>';
656  // This code hides the numeric price input if is not selected, loads the editor page if editor button is pressed
657  print '<script type="text/javascript">
658  jQuery(document).ready(run);
659  function run() {
660  jQuery("#expression_editor").click(on_click);
661  jQuery("#eid").change(on_change);
662  on_change();
663  }
664  function on_click() {
665  window.location = "'.DOL_URL_ROOT.'/product/dynamic_price/editor.php?id='.$id.'&tab=fournisseurs&eid=" + $("#eid").val();
666  }
667  function on_change() {
668  if ($("#eid").val() == 0) {
669  jQuery("#price_numeric").show();
670  } else {
671  jQuery("#price_numeric").hide();
672  }
673  }
674  </script>';
675  }
676 
677  if (isModEnabled("multicurrency")) {
678  // Currency
679  print '<tr><td class="fieldrequired">'.$langs->trans("Currency").'</td>';
680  print '<td>';
681  $currencycodetouse = GETPOST('multicurrency_code') ? GETPOST('multicurrency_code') : (isset($object->fourn_multicurrency_code) ? $object->fourn_multicurrency_code : '');
682  if (empty($currencycodetouse) && $object->fourn_multicurrency_tx == 1) {
683  $currencycodetouse = $conf->currency;
684  }
685  print $form->selectMultiCurrency($currencycodetouse, "multicurrency_code", 1);
686  print ' &nbsp; &nbsp; '.$langs->trans("CurrencyRate").' ';
687  print '<input class="flat" name="multicurrency_tx" size="4" value="'.vatrate(GETPOST('multicurrency_tx') ? GETPOST('multicurrency_tx') : (isset($object->fourn_multicurrency_tx) ? $object->fourn_multicurrency_tx : '')).'">';
688  print '</td>';
689  print '</tr>';
690 
691  // Currency price qty min
692  print '<tr><td class="fieldrequired">'.$form->textwithpicto($langs->trans("PriceQtyMinCurrency"), $langs->transnoentitiesnoconv("WithoutDiscount")).'</td>';
693  $pricesupplierincurrencytouse = (GETPOST('multicurrency_price') ? GETPOST('multicurrency_price') : (isset($object->fourn_multicurrency_price) ? $object->fourn_multicurrency_price : ''));
694  print '<td><input class="flat" name="multicurrency_price" size="8" value="'.price($pricesupplierincurrencytouse).'">';
695  print '&nbsp;';
696  print $form->selectPriceBaseType((GETPOST('multicurrency_price_base_type') ?GETPOST('multicurrency_price_base_type') : 'HT'), "multicurrency_price_base_type"); // We keep 'HT' here, multicurrency_price_base_type is not yet supported for supplier prices
697  print '</td></tr>';
698 
699  // Price qty min
700  print '<tr><td class="fieldrequired">'.$form->textwithpicto($langs->trans("PriceQtyMin"), $langs->transnoentitiesnoconv("WithoutDiscount")).'</td>';
701  print '<td><input class="flat" name="disabled_price" size="8" value="">';
702  print '<input type="hidden" name="price" value="">';
703  print '<input type="hidden" name="price_base_type" value="">';
704  print '&nbsp;';
705  print $form->selectPriceBaseType('', "disabled_price_base_type");
706  print '</td></tr>';
707 
708  $currencies = array();
709  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."multicurrency WHERE entity = ".((int) $conf->entity);
710  $resql = $db->query($sql);
711  if ($resql) {
712  $currency = new MultiCurrency($db);
713  while ($obj = $db->fetch_object($resql)) {
714  $currency->fetch($obj->rowid);
715  $currencies[$currency->code] = ((float) $currency->rate->rate);
716  }
717  }
718  $currencies = json_encode($currencies);
719 
720  print <<<END
721  <!-- javascript to autocalculate the minimum price -->
722  <script type="text/javascript">
723  function update_price_from_multicurrency() {
724  console.log("update_price_from_multicurrency");
725  var multicurrency_price = price2numjs($('input[name="multicurrency_price"]').val());
726  var multicurrency_tx = price2numjs($('input[name="multicurrency_tx"]').val());
727  if (multicurrency_tx != 0) {
728  $('input[name="price"]').val(multicurrency_price / multicurrency_tx);
729  $('input[name="disabled_price"]').val(multicurrency_price / multicurrency_tx);
730  } else {
731  $('input[name="price"]').val('');
732  $('input[name="disabled_price"]').val('');
733  }
734  }
735 
736  jQuery(document).ready(function () {
737  $('input[name="disabled_price"]').prop('disabled', true);
738  $('select[name="disabled_price_base_type"]').prop('disabled', true);
739  update_price_from_multicurrency();
740 
741  $('input[name="multicurrency_price"], input[name="multicurrency_tx"]').keyup(function () {
742  update_price_from_multicurrency();
743  });
744  $('input[name="multicurrency_price"], input[name="multicurrency_tx"]').change(function () {
745  update_price_from_multicurrency();
746  });
747  $('input[name="multicurrency_price"], input[name="multicurrency_tx"]').on('paste', function () {
748  update_price_from_multicurrency();
749  });
750 
751  $('select[name="multicurrency_price_base_type"]').change(function () {
752  $('input[name="price_base_type"]').val($(this).val());
753  $('select[name="disabled_price_base_type"]').val($(this).val());
754  });
755 
756  var currencies_array = $currencies;
757  $('select[name="multicurrency_code"]').change(function () {
758  console.log("We change the currency");
759  $('input[name="multicurrency_tx"]').val(currencies_array[$(this).val()]);
760  update_price_from_multicurrency();
761  });
762  });
763  </script>
764 END;
765  } else {
766  // Price qty min
767  print '<tr><td class="fieldrequired">'.$langs->trans("PriceQtyMin").'</td>';
768  print '<td><input class="flat" name="price" size="8" value="'.(GETPOST('price') ? price(GETPOST('price')) : (isset($object->fourn_price) ? price($object->fourn_price) : '')).'">';
769  print '&nbsp;';
770  print $form->selectPriceBaseType((GETPOSTISSET('price_base_type') ? GETPOST('price_base_type') : 'HT'), "price_base_type"); // We keep 'HT' here, price_base_type is not yet supported for supplier prices
771  print '</td></tr>';
772  }
773 
774  // Option to define a transport cost on supplier price
775  if (!empty($conf->global->PRODUCT_CHARGES)) {
776  print '<tr>';
777  print '<td>'.$langs->trans("Charges").'</td>';
778  print '<td><input class="flat" name="charges" size="8" value="'.(GETPOST('charges') ? price(GETPOST('charges')) : (isset($object->fourn_charges) ? price($object->fourn_charges) : '')).'">';
779  print '</td>';
780  print '</tr>';
781  }
782 
783  // Discount qty min
784  print '<tr><td>'.$langs->trans("DiscountQtyMin").'</td>';
785  print '<td><input class="flat" name="remise_percent" size="4" value="'.(GETPOSTISSET('remise_percent') ? vatrate(price2num(GETPOST('remise_percent'), '', 2)) : (isset($object->fourn_remise_percent) ?vatrate($object->fourn_remise_percent) : '')).'"> %';
786  print '</td>';
787  print '</tr>';
788 
789  // Delivery delay in days
790  print '<tr>';
791  print '<td>'.$langs->trans('NbDaysToDelivery').'</td>';
792  print '<td><input class="flat" name="delivery_time_days" size="4" value="'.($rowid ? $object->delivery_time_days : '').'">&nbsp;'.$langs->trans('days').'</td>';
793  print '</tr>';
794 
795  // Reputation
796  print '<tr><td>'.$langs->trans("ReferenceReputation").'</td><td>';
797  echo $form->selectarray('supplier_reputation', $object->reputations, !empty($supplier_reputation) ? $supplier_reputation : $object->supplier_reputation);
798  print '</td></tr>';
799 
800  // Barcode
801  if (isModEnabled('barcode')) {
802  $formbarcode = new FormBarCode($db);
803 
804  // Barcode type
805  print '<tr>';
806  print '<td>'.$langs->trans('GencodBuyPrice').'</td>';
807  print '<td>';
808  print img_picto('', 'barcode', 'class="pictofixedwidth"');
809  print $formbarcode->selectBarcodeType((GETPOSTISSET('fk_barcode_type') ? GETPOST('fk_barcode_type', 'int') : ($rowid ? $object->supplier_fk_barcode_type : getDolGlobalint("PRODUIT_DEFAULT_BARCODE_TYPE"))), 'fk_barcode_type', 1);
810  print ' <input class="flat" name="barcode" value="'.(GETPOSTISSET('barcode') ? GETPOST('barcode') : ($rowid ? $object->supplier_barcode : '')).'"></td>';
811  print '</tr>';
812  }
813 
814  // Product description of the supplier
815  if (!empty($conf->global->PRODUIT_FOURN_TEXTS)) {
816  //WYSIWYG Editor
817  require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
818 
819  print '<tr>';
820  print '<td>'.$langs->trans('ProductSupplierDescription').'</td>';
821  print '<td>';
822 
823  $doleditor = new DolEditor('supplier_description', $object->desc_supplier, '', 160, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_DETAILS'), ROWS_4, '90%');
824  $doleditor->Create();
825 
826  print '</td>';
827  print '</tr>';
828  }
829 
830  // Extrafields
831  $extrafields->fetch_name_optionals_label("product_fournisseur_price");
832  $extralabels = !empty($extrafields->attributes["product_fournisseur_price"]['label']) ? $extrafields->attributes["product_fournisseur_price"]['label'] : '';
833  $extrafield_values = $extrafields->getOptionalsFromPost("product_fournisseur_price");
834  if (!empty($extralabels)) {
835  if (empty($rowid)) {
836  foreach ($extralabels as $key => $value) {
837  if (!empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && ($extrafields->attributes["product_fournisseur_price"]['list'][$key] == 1 || $extrafields->attributes["product_fournisseur_price"]['list'][$key] == 3 || ($action == "update_price" && $extrafields->attributes["product_fournisseur_price"]['list'][$key] == 4))) {
838  if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
839  $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
840  }
841 
842  print '<tr><td'.($extrafields->attributes["product_fournisseur_price"]['required'][$key] ? ' class="fieldrequired"' : '').'>';
843  if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
844  print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
845  } else {
846  print $langs->trans($value);
847  }
848  print '</td><td>'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : '', '', '', '', '', 0, 'product_fournisseur_price').'</td></tr>';
849  }
850  }
851  } else {
852  $sql = "SELECT";
853  $sql .= " fk_object";
854  foreach ($extralabels as $key => $value) {
855  $sql .= ", ".$key;
856  }
857  $sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
858  $sql .= " WHERE fk_object = ".((int) $rowid);
859  $resql = $db->query($sql);
860  if ($resql) {
861  $obj = $db->fetch_object($resql);
862  foreach ($extralabels as $key => $value) {
863  if (!empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && ($extrafields->attributes["product_fournisseur_price"]['list'][$key] == 1 || $extrafields->attributes["product_fournisseur_price"]['list'][$key] == 3 || ($action == "update_price" && $extrafields->attributes["product_fournisseur_price"]['list'][$key] == 4))) {
864  if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
865  $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
866  }
867 
868  print '<tr><td'.($extrafields->attributes["product_fournisseur_price"]['required'][$key] ? ' class="fieldrequired"' : '').'>';
869  if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
870  print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
871  } else {
872  print $langs->trans($value);
873  }
874  print '</td><td>'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : $obj->{$key}, '', '', '', '', 0, 'product_fournisseur_price');
875 
876  print '</td></tr>';
877  }
878  }
879  $db->free($resql);
880  }
881  }
882  }
883 
884  if (is_object($hookmanager)) {
885  $parameters = array('id_fourn'=>!empty($id_fourn) ? $id_fourn : 0, 'prod_id'=>$object->id);
886  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action);
887  print $hookmanager->resPrint;
888  }
889 
890  print '</table>';
891 
892  print dol_get_fiche_end();
893 
894  print '<div class="center">';
895  print '<input class="button button-save" type="submit" value="'.$langs->trans("Save").'">';
896  print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
897  print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
898  print '</div>';
899 
900  print '</form>'."\n";
901  }
902 
903 
904  // Actions buttons
905 
906  print '<div class="tabsAction">'."\n";
907 
908  if ($action != 'add_price' && $action != 'update_price') {
909  $parameters = array();
910  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
911  if (empty($reshook)) {
912  if ($usercancreate) {
913  print '<a class="butAction" href="'.DOL_URL_ROOT.'/product/fournisseurs.php?id='.$object->id.'&action=add_price&token='.newToken().'">';
914  print $langs->trans("AddSupplierPrice").'</a>';
915  }
916  }
917  }
918 
919  print "</div>\n";
920 
921  if ($user->hasRight("fournisseur", "read")) { // Duplicate ? this check is already in the head of this file
922  $param = '';
923  if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
924  $param .= '&contextpage='.urlencode($contextpage);
925  }
926  if ($limit > 0 && $limit != $conf->liste_limit) {
927  $param .= '&limit='.urlencode($limit);
928  }
929  $param .= '&ref='.urlencode($object->ref);
930 
931  $product_fourn = new ProductFournisseur($db);
932  $product_fourn_list = $product_fourn->list_product_fournisseur_price($object->id, $sortfield, $sortorder, $limit, $offset);
933  $product_fourn_list_all = $product_fourn->list_product_fournisseur_price($object->id, $sortfield, $sortorder, 0, 0);
934  $nbtotalofrecords = count($product_fourn_list_all);
935  $num = count($product_fourn_list);
936  if (($num + ($offset * $limit)) < $nbtotalofrecords) {
937  $num++;
938  }
939 
940  print_barre_liste($langs->trans('SupplierPrices'), $page, $_SERVER['PHP_SELF'], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_accountancy.png', 0, '', '', $limit, 1);
941 
942  // Definition of fields for lists
943  // Some fields are missing because they are not included in the database query
944  $arrayfields = array(
945  'pfp.datec'=>array('label'=>$langs->trans("AppliedPricesFrom"), 'checked'=>1, 'position'=>1),
946  's.nom'=>array('label'=>$langs->trans("Suppliers"), 'checked'=>1, 'position'=>2),
947  'pfp.fk_availability'=>array('label'=>$langs->trans("Availability"), 'enabled' => getDolGlobalInt('FOURN_PRODUCT_AVAILABILITY'), 'checked'=>0, 'position'=>4),
948  'pfp.quantity'=>array('label'=>$langs->trans("QtyMin"), 'checked'=>1, 'position'=>5),
949  'pfp.unitprice'=>array('label'=>$langs->trans("UnitPriceHT"), 'checked'=>1, 'position'=>9),
950  'pfp.multicurrency_unitprice'=>array('label'=>$langs->trans("UnitPriceHTCurrency"), 'enabled' => isModEnabled('multicurrency'), 'checked'=>0, 'position'=>10),
951  'pfp.charges'=>array('label'=>$langs->trans("Charges"), 'enabled' => !empty($conf->global->PRODUCT_CHARGES), 'checked'=>0, 'position'=>11),
952  'pfp.delivery_time_days'=>array('label'=>$langs->trans("NbDaysToDelivery"), 'checked'=>-1, 'position'=>13),
953  'pfp.supplier_reputation'=>array('label'=>$langs->trans("ReputationForThisProduct"), 'checked'=>-1, 'position'=>14),
954  'pfp.fk_barcode_type'=>array('label'=>$langs->trans("BarcodeType"), 'enabled' => isModEnabled('barcode'), 'checked'=>0, 'position'=>15),
955  'pfp.barcode'=>array('label'=>$langs->trans("BarcodeValue"), 'enabled' => isModEnabled('barcode'), 'checked'=>0, 'position'=>16),
956  'pfp.packaging'=>array('label'=>$langs->trans("PackagingForThisProduct"), 'enabled' => getDolGlobalInt('PRODUCT_USE_SUPPLIER_PACKAGING'), 'checked'=>0, 'position'=>17),
957  'pfp.tms'=>array('label'=>$langs->trans("DateModification"), 'enabled' => isModEnabled('barcode'), 'checked'=>1, 'position'=>18),
958  );
959 
960  // fetch optionals attributes and labels
961  $extrafields->fetch_name_optionals_label("product_fournisseur_price");
962  if ($extrafields->attributes["product_fournisseur_price"] && array_key_exists('label', $extrafields->attributes["product_fournisseur_price"])) {
963  $extralabels = $extrafields->attributes["product_fournisseur_price"]['label'];
964 
965  if (!empty($extralabels)) {
966  foreach ($extralabels as $key => $value) {
967  // Show field if not hidden
968  if (!empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
969  $extratitle = $langs->trans($value);
970  $arrayfields['ef.' . $key] = array('label' => $extratitle, 'checked' => 0,
971  'position' => (end($arrayfields)['position'] + 1),
972  'langfile' => $extrafields->attributes["product_fournisseur_price"]['langfile'][$key],
973  'help' => $extrafields->attributes["product_fournisseur_price"]['help'][$key]);
974  }
975  }
976  }
977  }
978 
979  // Selection of new fields
980  include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
981 
982  $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
983  $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
984 
985  print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post" name="formulaire">';
986  print '<input type="hidden" name="token" value="'.newToken().'">';
987  print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
988  print '<input type="hidden" name="action" value="list">';
989  print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
990  print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
991 
992  // Suppliers list title
993  print '<div class="div-table-responsive">';
994  print '<table class="liste centpercent">';
995 
996  $param = "&id=".$object->id;
997 
998  $nbfields = 0;
999 
1000  print '<tr class="liste_titre">';
1001  if (!empty($arrayfields['pfp.datec']['checked'])) {
1002  print_liste_field_titre("AppliedPricesFrom", $_SERVER["PHP_SELF"], "pfp.datec", "", $param, "", $sortfield, $sortorder, '', '', 1);
1003  $nbfields++;
1004  }
1005  if (!empty($arrayfields['s.nom']['checked'])) {
1006  print_liste_field_titre("Suppliers", $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder, '', '', 1);
1007  $nbfields++;
1008  }
1009  print_liste_field_titre("SupplierRef", $_SERVER["PHP_SELF"], "", "", $param, "", $sortfield, $sortorder, '', '', 1);
1010  $nbfields++;
1011  if (!empty($arrayfields['pfp.fk_availability']['checked'])) {
1012  print_liste_field_titre("Availability", $_SERVER["PHP_SELF"], "pfp.fk_availability", "", $param, "", $sortfield, $sortorder);
1013  $nbfields++;
1014  }
1015  if (!empty($arrayfields['pfp.quantity']['checked'])) {
1016  print_liste_field_titre("QtyMin", $_SERVER["PHP_SELF"], "pfp.quantity", "", $param, '', $sortfield, $sortorder, 'right ');
1017  $nbfields++;
1018  }
1019  print_liste_field_titre("VATRate", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1020  $nbfields++;
1021  print_liste_field_titre("PriceQtyMinHT", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1022  $nbfields++;
1023  if (isModEnabled("multicurrency")) {
1024  print_liste_field_titre("PriceQtyMinHTCurrency", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1025  $nbfields++;
1026  }
1027  if (!empty($arrayfields['pfp.unitprice']['checked'])) {
1028  print_liste_field_titre("UnitPriceHT", $_SERVER["PHP_SELF"], "pfp.unitprice", "", $param, '', $sortfield, $sortorder, 'right ');
1029  $nbfields++;
1030  }
1031  if (!empty($arrayfields['pfp.multicurrency_unitprice']['checked'])) {
1032  print_liste_field_titre("UnitPriceHTCurrency", $_SERVER["PHP_SELF"], "pfp.multicurrency_unitprice", "", $param, '', $sortfield, $sortorder, 'right ');
1033  $nbfields++;
1034  }
1035  if (isModEnabled("multicurrency")) {
1036  print_liste_field_titre("Currency", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
1037  $nbfields++;
1038  }
1039  if (!empty($arrayfields['pfp.charges']['checked'])) {
1040  print_liste_field_titre("Charges", $_SERVER["PHP_SELF"], "pfp.charges", "", $param, '', $sortfield, $sortorder, 'right ');
1041  $nbfields++;
1042  }
1043  print_liste_field_titre("DiscountQtyMin", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1044  $nbfields++;
1045  if (!empty($arrayfields['pfp.delivery_time_days']['checked'])) {
1046  print_liste_field_titre("NbDaysToDelivery", $_SERVER["PHP_SELF"], "pfp.delivery_time_days", "", $param, '', $sortfield, $sortorder, 'right ');
1047  $nbfields++;
1048  }
1049  if (!empty($arrayfields['pfp.supplier_reputation']['checked'])) {
1050  print_liste_field_titre("ReputationForThisProduct", $_SERVER["PHP_SELF"], "pfp.supplier_reputation", "", $param, '', $sortfield, $sortorder, 'center ');
1051  $nbfields++;
1052  }
1053  if (!empty($arrayfields['pfp.fk_barcode_type']['checked'])) {
1054  print_liste_field_titre("BarcodeType", $_SERVER["PHP_SELF"], "pfp.fk_barcode_type", "", $param, '', $sortfield, $sortorder, 'center ');
1055  $nbfields++;
1056  }
1057  if (!empty($arrayfields['pfp.barcode']['checked'])) {
1058  print_liste_field_titre("BarcodeValue", $_SERVER["PHP_SELF"], "pfp.barcode", "", $param, '', $sortfield, $sortorder, 'center ');
1059  $nbfields++;
1060  }
1061  if (!empty($arrayfields['pfp.packaging']['checked'])) {
1062  print_liste_field_titre("PackagingForThisProduct", $_SERVER["PHP_SELF"], "pfp.packaging", "", $param, 'align="center"', $sortfield, $sortorder);
1063  $nbfields++;
1064  }
1065  if (!empty($arrayfields['pfp.tms']['checked'])) {
1066  print_liste_field_titre("DateModification", $_SERVER["PHP_SELF"], "pfp.tms", "", $param, '', $sortfield, $sortorder, 'right ', '', 1);
1067  $nbfields++;
1068  }
1069 
1070  // fetch optionals attributes and labels
1071  $extrafields->fetch_name_optionals_label("product_fournisseur_price");
1072  if ($extrafields->attributes["product_fournisseur_price"] && array_key_exists('label', $extrafields->attributes["product_fournisseur_price"])) {
1073  $extralabels = $extrafields->attributes["product_fournisseur_price"]['label'];
1074 
1075  if (!empty($extralabels)) {
1076  foreach ($extralabels as $key => $value) {
1077  // Show field if not hidden
1078  if (!empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1079  if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
1080  $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
1081  }
1082  if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
1083  $extratitle = $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
1084  } else {
1085  $extratitle = $langs->trans($value);
1086  }
1087  if (!empty($arrayfields['ef.' . $key]['checked'])) {
1088  print_liste_field_titre($extratitle, $_SERVER["PHP_SELF"], 'ef.' . $key, '', $param, '', $sortfield, $sortorder, 'right ');
1089  $nbfields++;
1090  }
1091  }
1092  }
1093  }
1094  }
1095 
1096  if (is_object($hookmanager)) {
1097  $parameters = array('id_fourn'=>(!empty($id_fourn)?$id_fourn:''), 'prod_id'=>$object->id, 'nbfields'=>$nbfields);
1098  $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action);
1099  }
1100  print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1101  $nbfields++;
1102  print "</tr>\n";
1103 
1104  if (is_array($product_fourn_list)) {
1105  foreach ($product_fourn_list as $productfourn) {
1106  print '<tr class="oddeven">';
1107 
1108  // Date from
1109  if (!empty($arrayfields['pfp.datec']['checked'])) {
1110  print '<td>'.dol_print_date(($productfourn->fourn_date_creation ? $productfourn->fourn_date_creation : $productfourn->date_creation), 'dayhour', 'tzuserrel').'</td>';
1111  }
1112 
1113  // Supplier
1114  if (!empty($arrayfields['s.nom']['checked'])) {
1115  print '<td class="tdoverflowmax150">'.$productfourn->getSocNomUrl(1, 'supplier').'</td>';
1116  }
1117 
1118  // Supplier ref
1119  if ($usercancreate) { // change required right here
1120  print '<td class="tdoverflowmax150">'.$productfourn->getNomUrl().'</td>';
1121  } else {
1122  print '<td class="tdoverflowmax150">'.dol_escape_htmltag($productfourn->fourn_ref).'</td>';
1123  }
1124 
1125  // Availability
1126  if (!empty($arrayfields['pfp.fk_availability']['checked'])) {
1127  $form->load_cache_availability();
1128  $availability = $form->cache_availability[$productfourn->fk_availability]['label'];
1129  print '<td class="left">'.$availability.'</td>';
1130  }
1131 
1132  // Quantity
1133  if (!empty($arrayfields['pfp.quantity']['checked'])) {
1134  print '<td class="right">';
1135  print $productfourn->fourn_qty;
1136  // Units
1137  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
1138  $unit = $object->getLabelOfUnit();
1139  if ($unit !== '') {
1140  print '&nbsp;&nbsp;'.$langs->trans($unit);
1141  }
1142  }
1143  print '</td>';
1144  }
1145 
1146  // VAT rate
1147  print '<td class="right">';
1148  print vatrate($productfourn->fourn_tva_tx, true);
1149  print '</td>';
1150 
1151  // Price for the quantity
1152  print '<td class="right">';
1153  print $productfourn->fourn_price ? '<span class="amount">'.price($productfourn->fourn_price).'</span>' : "";
1154  print '</td>';
1155 
1156  if (isModEnabled("multicurrency")) {
1157  // Price for the quantity in currency
1158  print '<td class="right">';
1159  print $productfourn->fourn_multicurrency_price ? '<span class="amount">'.price($productfourn->fourn_multicurrency_price).'</span>' : "";
1160  print '</td>';
1161  }
1162 
1163  // Unit price
1164  if (!empty($arrayfields['pfp.unitprice']['checked'])) {
1165  print '<td class="right">';
1166  print price($productfourn->fourn_unitprice);
1167  //print $objp->unitprice? price($objp->unitprice) : ($objp->quantity?price($objp->price/$objp->quantity):"&nbsp;");
1168  print '</td>';
1169  }
1170 
1171  // Unit price in currency
1172  if (!empty($arrayfields['pfp.multicurrency_unitprice']['checked'])) {
1173  print '<td class="right">';
1174  print price($productfourn->fourn_multicurrency_unitprice);
1175  print '</td>';
1176  }
1177 
1178  // Currency
1179  if (isModEnabled("multicurrency")) {
1180  print '<td class="right nowraponall">';
1181  print $productfourn->fourn_multicurrency_code ? currency_name($productfourn->fourn_multicurrency_code) : '';
1182  print '</td>';
1183  }
1184 
1185  // Charges
1186  if (!empty($arrayfields['pfp.charges']['checked'])) {
1187  print '<td class="right">';
1188  print price($productfourn->fourn_charges);
1189  print '</td>';
1190  }
1191 
1192  // Discount
1193  print '<td class="right">';
1194  print price2num($productfourn->fourn_remise_percent).'%';
1195  print '</td>';
1196 
1197  // Delivery delay
1198  if (!empty($arrayfields['pfp.delivery_time_days']['checked'])) {
1199  print '<td class="right">';
1200  print $productfourn->delivery_time_days;
1201  print '</td>';
1202  }
1203 
1204  // Reputation
1205  if (!empty($arrayfields['pfp.supplier_reputation']['checked'])) {
1206  print '<td class="center">';
1207  if (!empty($productfourn->supplier_reputation) && !empty($object->reputations[$productfourn->supplier_reputation])) {
1208  print $object->reputations[$productfourn->supplier_reputation];
1209  }
1210  print'</td>';
1211  }
1212 
1213  // Barcode type
1214  if (!empty($arrayfields['pfp.fk_barcode_type']['checked'])) {
1215  print '<td class="center">';
1216  $productfourn->barcode_type = !empty($productfourn->supplier_fk_barcode_type) ? $productfourn->supplier_fk_barcode_type : 0;
1217  $productfourn->fetch_barcode();
1218  print $productfourn->barcode_type_label ? $productfourn->barcode_type_label : ($productfourn->supplier_barcode ? '<div class="warning">'.$langs->trans("SetDefaultBarcodeType").'<div>' : '');
1219  print '</td>';
1220  }
1221 
1222  // Barcode
1223  if (!empty($arrayfields['pfp.barcode']['checked'])) {
1224  print '<td align="right">';
1225  print $productfourn->supplier_barcode;
1226  print '</td>';
1227  }
1228 
1229  // Packaging
1230  if (!empty($arrayfields['pfp.packaging']['checked'])) {
1231  print '<td align="center">';
1232  print price2num($productfourn->packaging);
1233  print '</td>';
1234  }
1235 
1236  // Date modification
1237  if (!empty($arrayfields['pfp.tms']['checked'])) {
1238  print '<td class="right nowraponall">';
1239  print dol_print_date(($productfourn->fourn_date_modification ? $productfourn->fourn_date_modification : $productfourn->date_modification), "dayhour");
1240  print '</td>';
1241  }
1242 
1243  // Extrafields
1244  if (!empty($extralabels)) {
1245  $sql = "SELECT";
1246  $sql .= " fk_object";
1247  foreach ($extralabels as $key => $value) {
1248  $sql .= ", ".$key;
1249  }
1250  $sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
1251  $sql .= " WHERE fk_object = ".((int) $productfourn->product_fourn_price_id);
1252  $resql = $db->query($sql);
1253  if ($resql) {
1254  if ($db->num_rows($resql) != 1) {
1255  foreach ($extralabels as $key => $value) {
1256  if (!empty($arrayfields['ef.'.$key]['checked']) && !empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1257  print "<td></td>";
1258  }
1259  }
1260  } else {
1261  $obj = $db->fetch_object($resql);
1262  foreach ($extralabels as $key => $value) {
1263  if (!empty($arrayfields['ef.'.$key]['checked']) && !empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1264  print '<td align="right">'.$extrafields->showOutputField($key, $obj->{$key}, '', 'product_fournisseur_price')."</td>";
1265  }
1266  }
1267  }
1268  $db->free($resql);
1269  }
1270  }
1271 
1272  if (is_object($hookmanager)) {
1273  $parameters = array('id_pfp'=>$productfourn->product_fourn_price_id, 'id_fourn'=>(!empty($id_fourn)?$id_fourn:''), 'prod_id'=>$object->id);
1274  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action);
1275  }
1276 
1277  // Modify-Remove
1278  print '<td class="center nowraponall">';
1279 
1280  if ($usercancreate) {
1281  print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?id='.((int) $object->id).'&socid='.((int) $productfourn->fourn_id).'&action=update_price&token='.newToken().'&rowid='.((int) $productfourn->product_fourn_price_id).'">'.img_edit()."</a>";
1282  print ' &nbsp; ';
1283  print '<a href="'.$_SERVER['PHP_SELF'].'?id='.((int) $object->id).'&socid='.((int) $productfourn->fourn_id).'&action=ask_remove_pf&token='.newToken().'&rowid='.((int) $productfourn->product_fourn_price_id).'">'.img_picto($langs->trans("Remove"), 'delete').'</a>';
1284  }
1285 
1286  print '</td>';
1287 
1288  print '</tr>';
1289  }
1290 
1291  if (empty($product_fourn_list)) {
1292  print '<tr><td colspan="'.$nbfields.'"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
1293  }
1294  } else {
1295  dol_print_error($db);
1296  }
1297 
1298  print '</table>';
1299  print '</div>';
1300  print '</form>';
1301  }
1302  }
1303  }
1304 } else {
1305  print $langs->trans("ErrorUnknown");
1306 }
1307 
1308 // End of page
1309 llxFooter();
1310 $db->close();
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
Class to manage a WYSIWYG editor.
Class to manage standard extra fields.
Class to manage barcode HTML.
Class to manage generation of HTML components Only common components must be here.
Class to manage suppliers.
Class Currency.
Class for accesing price expression table.
Class to parse product price expressions.
Class to manage predefined suppliers products.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
currency_name($code_iso, $withcode='', $outputlangs=null)
Return label of currency or code+label.
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:745
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
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.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formated for view output Used into pdf and HTML pages.
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='')
Show tabs of a record.
GETPOSTINT($paramname, $method=0)
Return value of a param into GET or POST supervariable.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages 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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
newToken()
Return the value of token currently saved into session with name 'newtoken'.
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Fonction qui renvoie si tva doit etre tva percue recuperable.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier fiche.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
price2numjs(amount)
Function similar to PHP price2num()
$formconfirm
if ($action == 'delbookkeepingyear') {
div float
Buy price without taxes.
Definition: style.css.php:913
$nbtotalofrecords
Count total nb of records.
Definition: list.php:329
product_prepare_head($object)
Prepare array with list of tabs.
Definition: product.lib.php:35
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.