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  $id_fourn = GETPOST("id_fourn");
186  if (empty($id_fourn)) {
187  $id_fourn = GETPOST("search_id_fourn");
188  }
189  $ref_fourn = GETPOST("ref_fourn");
190  if (empty($ref_fourn)) {
191  $ref_fourn = GETPOST("search_ref_fourn");
192  }
193  $ref_fourn_old = GETPOST("ref_fourn_old");
194  if (empty($ref_fourn_old)) {
195  $ref_fourn_old = $ref_fourn;
196  }
197  $quantity = price2num(GETPOST("qty", 'alphanohtml'), 'MS');
198  $remise_percent = price2num(GETPOST('remise_percent', 'alpha'));
199 
200  $npr = preg_match('/\*/', GETPOST('tva_tx', 'alpha')) ? 1 : 0;
201  $tva_tx = str_replace('*', '', GETPOST('tva_tx', 'alpha'));
202  if (!preg_match('/\‍((.*)\‍)/', $tva_tx)) {
203  $tva_tx = price2num($tva_tx);
204  }
205 
206  $price_expression = GETPOST('eid', 'int') ? GETPOST('eid', 'int') : ''; // Discard expression if not in expression mode
207  $delivery_time_days = GETPOST('delivery_time_days', 'int') ? GETPOST('delivery_time_days', 'int') : '';
208  $supplier_reputation = GETPOST('supplier_reputation');
209  $supplier_description = GETPOST('supplier_description', 'restricthtml');
210  $barcode = GETPOST('barcode', 'alpha');
211  $fk_barcode_type = GETPOST('fk_barcode_type', 'int');
212  $packaging = price2num(GETPOST("packaging", 'alphanohtml'), 'MS');
213 
214  if ($tva_tx == '') {
215  $error++;
216  $langs->load("errors");
217  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("VATRateForSupplierProduct")), null, 'errors');
218  }
219  if (!is_numeric($tva_tx)) {
220  $error++;
221  $langs->load("errors");
222  setEventMessages($langs->trans("ErrorFieldMustBeANumeric", $langs->transnoentities("VATRateForSupplierProduct")), null, 'errors');
223  }
224  if (empty($quantity)) {
225  $error++;
226  $langs->load("errors");
227  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Qty")), null, 'errors');
228  }
229  if (empty($ref_fourn)) {
230  $error++;
231  $langs->load("errors");
232  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("RefSupplier")), null, 'errors');
233  }
234  if ($id_fourn <= 0) {
235  $error++;
236  $langs->load("errors");
237  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Supplier")), null, 'errors');
238  }
239  if (price2num(GETPOST("price")) < 0 || GETPOST("price") == '') {
240  if ($price_expression === '') { // Return error of missing price only if price_expression not set
241  $error++;
242  $langs->load("errors");
243  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Price")), null, 'errors');
244  } else {
245  $_POST["price"] = 0;
246  }
247  }
248  if (isModEnabled("multicurrency")) {
249  if (!GETPOST("multicurrency_code")) {
250  $error++;
251  $langs->load("errors");
252  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Currency")), null, 'errors');
253  }
254  if (price2num(GETPOST("multicurrency_tx")) <= 0 || GETPOST("multicurrency_tx") == '') {
255  $error++;
256  $langs->load("errors");
257  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("CurrencyRate")), null, 'errors');
258  }
259  if (price2num(GETPOST("multicurrency_price")) < 0 || GETPOST("multicurrency_price") == '') {
260  $error++;
261  $langs->load("errors");
262  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("PriceCurrency")), null, 'errors');
263  }
264  }
265 
266  if (!$error) {
267  $db->begin();
268 
269  if (!$error) {
270  $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
271  if ($ret == -3) {
272  $error++;
273 
274  $tmpobject = new Product($db);
275  $tmpobject->fetch($object->product_id_already_linked);
276  $productLink = $tmpobject->getNomUrl(1, 'supplier');
277 
278  $texttoshow = $langs->trans("ReferenceSupplierIsAlreadyAssociatedWithAProduct", '{s1}');
279  $texttoshow = str_replace('{s1}', $productLink, $texttoshow);
280  setEventMessages($texttoshow, null, 'errors');
281  } elseif ($ret < 0) {
282  $error++;
283  setEventMessages($object->error, $object->errors, 'errors');
284  }
285  }
286 
287  if (!$error) {
288  $supplier = new Fournisseur($db);
289  $result = $supplier->fetch($id_fourn);
290  if (GETPOSTISSET('ref_fourn_price_id')) {
291  $object->fetch_product_fournisseur_price(GETPOST('ref_fourn_price_id', 'int'));
292  }
293  $extralabels = $extrafields->fetch_name_optionals_label("product_fournisseur_price");
294  $extrafield_values = $extrafields->getOptionalsFromPost("product_fournisseur_price");
295 
296  $newprice = price2num(GETPOST("price", "alpha"));
297 
298  if (empty($packaging)) {
299  $packaging = 1;
300  }
301  /* We can have a puchase ref that need to buy 100 min for a given price and with a packaging of 50.
302  if ($packaging < $quantity) {
303  $packaging = $quantity;
304  }*/
305  $object->packaging = $packaging;
306 
307  if (isModEnabled("multicurrency")) {
308  $multicurrency_tx = price2num(GETPOST("multicurrency_tx", 'alpha'));
309  $multicurrency_price = price2num(GETPOST("multicurrency_price", 'alpha'));
310  $multicurrency_code = GETPOST("multicurrency_code", 'alpha');
311 
312  $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);
313  } else {
314  $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);
315  }
316  if ($ret < 0) {
317  $error++;
318  setEventMessages($object->error, $object->errors, 'errors');
319  } else {
320  if (isModEnabled('dynamicprices') && $price_expression !== '') {
321  //Check the expression validity by parsing it
322  require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
323  $priceparser = new PriceParser($db);
324  $object->fk_supplier_price_expression = $price_expression;
325  $price_result = $priceparser->parseProductSupplier($object);
326  if ($price_result < 0) { //Expression is not valid
327  $error++;
328  setEventMessages($priceparser->translatedError(), null, 'errors');
329  }
330  }
331  if (!$error && isModEnabled('dynamicprices')) {
332  //Set the price expression for this supplier price
333  $ret = $object->setSupplierPriceExpression($price_expression);
334  if ($ret < 0) {
335  $error++;
336  setEventMessages($object->error, $object->errors, 'errors');
337  }
338  }
339  }
340  }
341 
342  if (!$error) {
343  $db->commit();
344  $action = '';
345  } else {
346  $db->rollback();
347  }
348  } else {
349  $action = 'add_price';
350  }
351  }
352 }
353 
354 
355 /*
356  * view
357  */
358 
359 $form = new Form($db);
360 
361 $title = $langs->trans('ProductServiceCard');
362 $helpurl = '';
363 $shortlabel = dol_trunc($object->label, 16);
364 if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) {
365  $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('BuyingPrices');
366  $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos|DE:Modul_Produkte';
367 }
368 if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) {
369  $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('BuyingPrices');
370  $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios|DE:Modul_Lesitungen';
371 }
372 
373 llxHeader('', $title, $helpurl, '', 0, 0, '', '', '', 'classforhorizontalscrolloftabs');
374 
375 if ($id > 0 || $ref) {
376  if ($result) {
377  if ($action == 'ask_remove_pf') {
378  $form = new Form($db);
379  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$id.'&rowid='.$rowid, $langs->trans('DeleteProductBuyPrice'), $langs->trans('ConfirmDeleteProductBuyPrice'), 'confirm_remove_pf', '', 0, 1);
380  echo $formconfirm;
381  }
382 
383  if ($action != 'edit' && $action != 're-edit') {
384  $head = product_prepare_head($object);
385  $titre = $langs->trans("CardProduct".$object->type);
386  $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
387 
388  print dol_get_fiche_head($head, 'suppliers', $titre, -1, $picto);
389 
390  $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
391  $object->next_prev_filter = " fk_product_type = ".$object->type;
392 
393  $shownav = 1;
394  if ($user->socid && !in_array('product', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) {
395  $shownav = 0;
396  }
397 
398  dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
399 
400  print '<div class="fichecenter">';
401 
402  print '<div class="underbanner clearboth"></div>';
403  print '<table class="border tableforfield centpercent">';
404 
405  // Type
406  if (isModEnabled("product") && isModEnabled("service")) {
407  $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service");
408  print '<tr><td class="">';
409  print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type');
410  print '</td><td>';
411  print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat);
412  print '</td></tr>';
413  }
414 
415  // Cost price. Can be used for margin module for option "calculate margin on explicit cost price
416  print '<tr><td>';
417  $textdesc = $langs->trans("CostPriceDescription");
418  $textdesc .= "<br>".$langs->trans("CostPriceUsage");
419  $text = $form->textwithpicto($langs->trans("CostPrice"), $textdesc, 1, 'help', '');
420  print $form->editfieldkey($text, 'cost_price', $object->cost_price, $object, $usercancreate, 'amount:6');
421  print '</td><td>';
422  print $form->editfieldval($text, 'cost_price', $object->cost_price, $object, $usercancreate, 'amount:6');
423  print '</td></tr>';
424 
425  // PMP
426  $usercaneditpmp = 0;
427  if (!empty($conf->global->PRODUCT_CAN_EDIT_WAP)) {
428  $usercaneditpmp = $usercancreate;
429  }
430  print '<tr><td class="titlefieldcreate">';
431  $textdesc = $langs->trans("AverageUnitPricePMPDesc");
432  $text = $form->textwithpicto($langs->trans("AverageUnitPricePMPShort"), $textdesc, 1, 'help', '');
433  print $form->editfieldkey($text, 'pmp', $object->pmp, $object, $usercaneditpmp, 'amount:6');
434  print '</td><td>';
435  print $form->editfieldval($text, 'pmp', ($object->pmp > 0 ? $object->pmp : ''), $object, $usercaneditpmp, 'amount:6');
436  if ($object->pmp > 0) {
437  print ' '.$langs->trans("HT");
438  }
439  /*
440  .$form->textwithpicto($langs->trans("AverageUnitPricePMPShort"), $langs->trans("AverageUnitPricePMPDesc")).'</td>';
441  print '<td>';
442  if ($object->pmp > 0) {
443  print price($object->pmp).' '.$langs->trans("HT");
444  }*/
445  print '</td>';
446  print '</tr>';
447 
448  // Best buying Price
449  print '<tr><td class="titlefieldcreate">'.$langs->trans("BuyingPriceMin").'</td>';
450  print '<td>';
451  $product_fourn = new ProductFournisseur($db);
452  if ($product_fourn->find_min_price_product_fournisseur($object->id) > 0) {
453  if ($product_fourn->product_fourn_price_id > 0) {
454  print $product_fourn->display_price_product_fournisseur();
455  } else {
456  print $langs->trans("NotDefined");
457  }
458  }
459  print '</td></tr>';
460 
461  print '</table>';
462 
463  print '</div>';
464  print '<div style="clear:both"></div>';
465 
466  print dol_get_fiche_end();
467 
468 
469  // Form to add or update a price
470  if (($action == 'add_price' || $action == 'update_price') && $usercancreate) {
471  $langs->load("suppliers");
472 
473  print "<!-- form to add a supplier price -->\n";
474  print '<br>';
475 
476  if ($rowid) {
477  $object->fetch_product_fournisseur_price($rowid, 1); //Ignore the math expression when getting the price
478  print load_fiche_titre($langs->trans("ChangeSupplierPrice"));
479  } else {
480  print load_fiche_titre($langs->trans("AddSupplierPrice"));
481  }
482 
483  print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="POST">';
484  print '<input type="hidden" name="token" value="'.newToken().'">';
485  print '<input type="hidden" name="action" value="save_price">';
486 
487  print dol_get_fiche_head();
488 
489  print '<table class="border centpercent">';
490 
491  // Supplier
492  print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Supplier").'</td><td>';
493  if ($rowid) {
494  $supplier = new Fournisseur($db);
495  $supplier->fetch($socid);
496  print $supplier->getNomUrl(1);
497  print '<input type="hidden" name="id_fourn" value="'.$socid.'">';
498  print '<input type="hidden" name="ref_fourn_price_id" value="'.$rowid.'">';
499  print '<input type="hidden" name="rowid" value="'.$rowid.'">';
500  print '<input type="hidden" name="socid" value="'.$socid.'">';
501  } else {
502  $events = array();
503  $events[] = array('method' => 'getVatRates', 'url' => dol_buildpath('/core/ajax/vatrates.php', 1), 'htmlname' => 'tva_tx', 'params' => array());
504  print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(GETPOST("id_fourn", 'alpha'), 'id_fourn', 'fournisseur=1', 'SelectThirdParty', 0, 0, $events);
505 
506  $parameters = array('filtre'=>"fournisseur=1", 'html_name'=>'id_fourn', 'selected'=>GETPOST("id_fourn"), 'showempty'=>1, 'prod_id'=>$object->id);
507  $reshook = $hookmanager->executeHooks('formCreateThirdpartyOptions', $parameters, $object, $action);
508  if (empty($reshook)) {
509  if (empty($form->result)) {
510  print '<a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&type=f&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id.'&action='.$action).'">';
511  print img_picto($langs->trans("CreateDolibarrThirdPartySupplier"), 'add', 'class="marginleftonly"');
512  print '</a>';
513  }
514  }
515  print '<script type="text/javascript">
516  $(document).ready(function () {
517  $("#search_id_fourn").change(load_vat)
518  console.log("Requesting default VAT rate for the supplier...")
519  });
520  function load_vat() {
521  // get soc id
522  let socid = $("#id_fourn")[0].value
523 
524  // load available VAT rates
525  let vat_url = "'.dol_buildpath('/core/ajax/vatrates.php', 1).'"
526  //Make GET request with params
527  let options = "";
528  options += "id=" + socid
529  options += "&htmlname=tva_tx"
530  options += "&action=default" // not defined in vatrates.php, default behavior.
531 
532  var get = $.getJSON(
533  vat_url,
534  options,
535  (data) => {
536  rate_options = $.parseHTML(data.value)
537  rate_options.forEach(opt => {
538  if (opt.selected) {
539  replaceVATWithSupplierValue(opt.value)
540  return
541  }
542  })
543  }
544  );
545 
546  }
547  function replaceVATWithSupplierValue(vat_rate) {
548  console.log("Default VAT rate for the supplier: " + vat_rate + "%")
549  $("[name=\'tva_tx\']")[0].value = vat_rate;
550  }
551  </script>';
552  }
553  print '</td></tr>';
554 
555  // Ref supplier
556  print '<tr><td class="fieldrequired">'.$langs->trans("SupplierRef").'</td><td>';
557  if ($rowid) {
558  print '<input type="hidden" name="ref_fourn_old" value="'.$object->ref_supplier.'">';
559  print '<input class="flat width150" maxlength="128" name="ref_fourn" value="'.$object->ref_supplier.'">';
560  } else {
561  print '<input class="flat width150" maxlength="128" name="ref_fourn" value="'.(GETPOST("ref_fourn") ? GETPOST("ref_fourn") : '').'">';
562  }
563  print '</td>';
564  print '</tr>';
565 
566  // Availability
567  if (getDolGlobalInt('FOURN_PRODUCT_AVAILABILITY')) {
568  $langs->load("propal");
569  print '<tr><td>'.$langs->trans("Availability").'</td><td>';
570  $form->selectAvailabilityDelay($object->fk_availability, "oselDispo", 1);
571  print '</td></tr>'."\n";
572  }
573 
574  // Qty min
575  print '<tr>';
576  print '<td class="fieldrequired">'.$langs->trans("QtyMin").'</td>';
577  print '<td>';
578  $quantity = GETPOSTISSET('qty') ? price2num(GETPOST('qty', 'alphanohtml'), 'MS') : "1";
579  if ($rowid) {
580  print '<input type="hidden" name="qty" value="'.$object->fourn_qty.'">';
581  print $object->fourn_qty;
582  } else {
583  print '<input class="flat" name="qty" size="5" value="'.$quantity.'">';
584  }
585  // Units
586  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
587  $unit = $object->getLabelOfUnit();
588  if ($unit !== '') {
589  print '&nbsp;&nbsp;'.$langs->trans($unit);
590  }
591  }
592  print '</td></tr>';
593 
594  if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
595  // Packaging/Conditionnement
596  print '<tr>';
597 
598  print '<td class="fieldrequired">'.$form->textwithpicto($langs->trans("PackagingForThisProduct"), $langs->trans("PackagingForThisProductDesc")).'</td>';
599  print '<td>';
600  $packaging = GETPOSTISSET('packaging') ? price2num(GETPOST('packaging', 'alphanohtml'), 'MS') : ((empty($rowid)) ? "1" : price2num($object->packaging, 'MS'));
601  print '<input class="flat" name="packaging" size="5" value="'.$packaging.'">';
602 
603  // Units
604  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
605  $unit = $object->getLabelOfUnit();
606  if ($unit !== '') {
607  print '&nbsp;&nbsp;'.$langs->trans($unit);
608  }
609  }
610  }
611  // Vat rate
612  $default_vat = '';
613 
614  // We don't have supplier, so we try to guess.
615  // For this we build a fictive supplier with same properties than user but using vat)
616  $mysoc2 = clone $mysoc;
617  $mysoc2->name = 'Fictive seller with same country';
618  $mysoc2->tva_assuj = 1;
619  $default_vat = get_default_tva($mysoc2, $mysoc, $object->id, 0);
620  $default_npr = get_default_npr($mysoc2, $mysoc, $object->id, 0);
621  if (empty($default_vat)) {
622  $default_npr = $default_vat;
623  }
624 
625  print '<tr><td class="fieldrequired">'.$langs->trans("VATRateForSupplierProduct").'</td>';
626  print '<td>';
627  //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
628  if (!empty($rowid)) { // If we have a supplier, it is an update, we must show the vat of current supplier price
629  $tmpproductsupplier = new ProductFournisseur($db);
630  $tmpproductsupplier->fetch_product_fournisseur_price($rowid, 1);
631  $default_vat = $tmpproductsupplier->fourn_tva_tx;
632  $default_npr = $tmpproductsupplier->fourn_tva_npr;
633  } else {
634  if (empty($default_vat)) {
635  $default_vat = $object->tva_tx;
636  }
637  }
638  $vattosuggest = (GETPOSTISSET("tva_tx") ? vatrate(GETPOST("tva_tx")) : ($default_vat != '' ?vatrate($default_vat) : ''));
639  $vattosuggest = preg_replace('/\s*\‍(.*\‍)$/', '', $vattosuggest);
640  print '<input type="text" class="flat" size="5" name="tva_tx" value="'.$vattosuggest.'">';
641  print '</td></tr>';
642 
643  if (isModEnabled('dynamicprices')) { //Only show price mode and expression selector if module is enabled
644  // Price mode selector
645  print '<tr><td class="fieldrequired">'.$langs->trans("PriceMode").'</td><td>';
646  $price_expression = new PriceExpression($db);
647  $price_expression_list = array(0 => $langs->trans("PriceNumeric")); //Put the numeric mode as first option
648  foreach ($price_expression->list_price_expression() as $entry) {
649  $price_expression_list[$entry->id] = $entry->title;
650  }
651  $price_expression_preselection = GETPOST('eid') ? GETPOST('eid') : ($object->fk_supplier_price_expression ? $object->fk_supplier_price_expression : '0');
652  print $form->selectarray('eid', $price_expression_list, $price_expression_preselection);
653  print '&nbsp; <div id="expression_editor" class="button">'.$langs->trans("PriceExpressionEditor").'</div>';
654  print '</td></tr>';
655  // This code hides the numeric price input if is not selected, loads the editor page if editor button is pressed
656  print '<script type="text/javascript">
657  jQuery(document).ready(run);
658  function run() {
659  jQuery("#expression_editor").click(on_click);
660  jQuery("#eid").change(on_change);
661  on_change();
662  }
663  function on_click() {
664  window.location = "'.DOL_URL_ROOT.'/product/dynamic_price/editor.php?id='.$id.'&tab=fournisseurs&eid=" + $("#eid").val();
665  }
666  function on_change() {
667  if ($("#eid").val() == 0) {
668  jQuery("#price_numeric").show();
669  } else {
670  jQuery("#price_numeric").hide();
671  }
672  }
673  </script>';
674  }
675 
676  if (isModEnabled("multicurrency")) {
677  // Currency
678  print '<tr><td class="fieldrequired">'.$langs->trans("Currency").'</td>';
679  print '<td>';
680  $currencycodetouse = GETPOST('multicurrency_code') ? GETPOST('multicurrency_code') : (isset($object->fourn_multicurrency_code) ? $object->fourn_multicurrency_code : '');
681  if (empty($currencycodetouse) && $object->fourn_multicurrency_tx == 1) {
682  $currencycodetouse = $conf->currency;
683  }
684  print $form->selectMultiCurrency($currencycodetouse, "multicurrency_code", 1);
685  print ' &nbsp; &nbsp; '.$langs->trans("CurrencyRate").' ';
686  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 : '')).'">';
687  print '</td>';
688  print '</tr>';
689 
690  // Currency price qty min
691  print '<tr><td class="fieldrequired">'.$form->textwithpicto($langs->trans("PriceQtyMinCurrency"), $langs->transnoentitiesnoconv("WithoutDiscount")).'</td>';
692  $pricesupplierincurrencytouse = (GETPOST('multicurrency_price') ? GETPOST('multicurrency_price') : (isset($object->fourn_multicurrency_price) ? $object->fourn_multicurrency_price : ''));
693  print '<td><input class="flat" name="multicurrency_price" size="8" value="'.price($pricesupplierincurrencytouse).'">';
694  print '&nbsp;';
695  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
696  print '</td></tr>';
697 
698  // Price qty min
699  print '<tr><td class="fieldrequired">'.$form->textwithpicto($langs->trans("PriceQtyMin"), $langs->transnoentitiesnoconv("WithoutDiscount")).'</td>';
700  print '<td><input class="flat" name="disabled_price" size="8" value="">';
701  print '<input type="hidden" name="price" value="">';
702  print '<input type="hidden" name="price_base_type" value="">';
703  print '&nbsp;';
704  print $form->selectPriceBaseType('', "disabled_price_base_type");
705  print '</td></tr>';
706 
707  $currencies = array();
708  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."multicurrency WHERE entity = ".((int) $conf->entity);
709  $resql = $db->query($sql);
710  if ($resql) {
711  $currency = new MultiCurrency($db);
712  while ($obj = $db->fetch_object($resql)) {
713  $currency->fetch($obj->rowid);
714  $currencies[$currency->code] = ((float) $currency->rate->rate);
715  }
716  }
717  $currencies = json_encode($currencies);
718 
719  print <<<END
720  <!-- javascript to autocalculate the minimum price -->
721  <script type="text/javascript">
722  function update_price_from_multicurrency() {
723  console.log("update_price_from_multicurrency");
724  var multicurrency_price = price2numjs($('input[name="multicurrency_price"]').val());
725  var multicurrency_tx = price2numjs($('input[name="multicurrency_tx"]').val());
726  if (multicurrency_tx != 0) {
727  $('input[name="price"]').val(multicurrency_price / multicurrency_tx);
728  $('input[name="disabled_price"]').val(multicurrency_price / multicurrency_tx);
729  } else {
730  $('input[name="price"]').val('');
731  $('input[name="disabled_price"]').val('');
732  }
733  }
734 
735  jQuery(document).ready(function () {
736  $('input[name="disabled_price"]').prop('disabled', true);
737  $('select[name="disabled_price_base_type"]').prop('disabled', true);
738  update_price_from_multicurrency();
739 
740  $('input[name="multicurrency_price"], input[name="multicurrency_tx"]').keyup(function () {
741  update_price_from_multicurrency();
742  });
743  $('input[name="multicurrency_price"], input[name="multicurrency_tx"]').change(function () {
744  update_price_from_multicurrency();
745  });
746  $('input[name="multicurrency_price"], input[name="multicurrency_tx"]').on('paste', function () {
747  update_price_from_multicurrency();
748  });
749 
750  $('select[name="multicurrency_price_base_type"]').change(function () {
751  $('input[name="price_base_type"]').val($(this).val());
752  $('select[name="disabled_price_base_type"]').val($(this).val());
753  });
754 
755  var currencies_array = $currencies;
756  $('select[name="multicurrency_code"]').change(function () {
757  console.log("We change the currency");
758  $('input[name="multicurrency_tx"]').val(currencies_array[$(this).val()]);
759  update_price_from_multicurrency();
760  });
761  });
762  </script>
763 END;
764  } else {
765  // Price qty min
766  print '<tr><td class="fieldrequired">'.$langs->trans("PriceQtyMin").'</td>';
767  print '<td><input class="flat" name="price" size="8" value="'.(GETPOST('price') ? price(GETPOST('price')) : (isset($object->fourn_price) ? price($object->fourn_price) : '')).'">';
768  print '&nbsp;';
769  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
770  print '</td></tr>';
771  }
772 
773  // Option to define a transport cost on supplier price
774  if (!empty($conf->global->PRODUCT_CHARGES)) {
775  print '<tr>';
776  print '<td>'.$langs->trans("Charges").'</td>';
777  print '<td><input class="flat" name="charges" size="8" value="'.(GETPOST('charges') ? price(GETPOST('charges')) : (isset($object->fourn_charges) ? price($object->fourn_charges) : '')).'">';
778  print '</td>';
779  print '</tr>';
780  }
781 
782  // Discount qty min
783  print '<tr><td>'.$langs->trans("DiscountQtyMin").'</td>';
784  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) : '')).'"> %';
785  print '</td>';
786  print '</tr>';
787 
788  // Delivery delay in days
789  print '<tr>';
790  print '<td>'.$langs->trans('NbDaysToDelivery').'</td>';
791  print '<td><input class="flat" name="delivery_time_days" size="4" value="'.($rowid ? $object->delivery_time_days : '').'">&nbsp;'.$langs->trans('days').'</td>';
792  print '</tr>';
793 
794  // Reputation
795  print '<tr><td>'.$langs->trans("ReferenceReputation").'</td><td>';
796  echo $form->selectarray('supplier_reputation', $object->reputations, !empty($supplier_reputation) ? $supplier_reputation : $object->supplier_reputation);
797  print '</td></tr>';
798 
799  // Barcode
800  if (isModEnabled('barcode')) {
801  $formbarcode = new FormBarCode($db);
802 
803  // Barcode type
804  print '<tr>';
805  print '<td>'.$langs->trans('GencodBuyPrice').'</td>';
806  print '<td>';
807  print img_picto('', 'barcode', 'class="pictofixedwidth"');
808  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);
809  print ' <input class="flat" name="barcode" value="'.(GETPOSTISSET('barcode') ? GETPOST('barcode') : ($rowid ? $object->supplier_barcode : '')).'"></td>';
810  print '</tr>';
811  }
812 
813  // Product description of the supplier
814  if (!empty($conf->global->PRODUIT_FOURN_TEXTS)) {
815  //WYSIWYG Editor
816  require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
817 
818  print '<tr>';
819  print '<td>'.$langs->trans('ProductSupplierDescription').'</td>';
820  print '<td>';
821 
822  $doleditor = new DolEditor('supplier_description', $object->desc_supplier, '', 160, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_DETAILS'), ROWS_4, '90%');
823  $doleditor->Create();
824 
825  print '</td>';
826  print '</tr>';
827  }
828 
829  // Extrafields
830  $extrafields->fetch_name_optionals_label("product_fournisseur_price");
831  $extralabels = !empty($extrafields->attributes["product_fournisseur_price"]['label']) ? $extrafields->attributes["product_fournisseur_price"]['label'] : '';
832  $extrafield_values = $extrafields->getOptionalsFromPost("product_fournisseur_price");
833  if (!empty($extralabels)) {
834  if (empty($rowid)) {
835  foreach ($extralabels as $key => $value) {
836  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))) {
837  if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
838  $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
839  }
840 
841  print '<tr><td'.($extrafields->attributes["product_fournisseur_price"]['required'][$key] ? ' class="fieldrequired"' : '').'>';
842  if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
843  print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
844  } else {
845  print $langs->trans($value);
846  }
847  print '</td><td>'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : '', '', '', '', '', 0, 'product_fournisseur_price').'</td></tr>';
848  }
849  }
850  } else {
851  $sql = "SELECT";
852  $sql .= " fk_object";
853  foreach ($extralabels as $key => $value) {
854  $sql .= ", ".$key;
855  }
856  $sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
857  $sql .= " WHERE fk_object = ".((int) $rowid);
858  $resql = $db->query($sql);
859  if ($resql) {
860  $obj = $db->fetch_object($resql);
861  foreach ($extralabels as $key => $value) {
862  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))) {
863  if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
864  $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
865  }
866 
867  print '<tr><td'.($extrafields->attributes["product_fournisseur_price"]['required'][$key] ? ' class="fieldrequired"' : '').'>';
868  if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
869  print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
870  } else {
871  print $langs->trans($value);
872  }
873  print '</td><td>'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : $obj->{$key}, '', '', '', '', 0, 'product_fournisseur_price');
874 
875  print '</td></tr>';
876  }
877  }
878  $db->free($resql);
879  }
880  }
881  }
882 
883  if (is_object($hookmanager)) {
884  $parameters = array('id_fourn'=>!empty($id_fourn) ? $id_fourn : 0, 'prod_id'=>$object->id);
885  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action);
886  print $hookmanager->resPrint;
887  }
888 
889  print '</table>';
890 
891  print dol_get_fiche_end();
892 
893  print '<div class="center">';
894  print '<input class="button button-save" type="submit" value="'.$langs->trans("Save").'">';
895  print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
896  print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
897  print '</div>';
898 
899  print '</form>'."\n";
900  }
901 
902 
903  // Actions buttons
904 
905  print '<div class="tabsAction">'."\n";
906 
907  if ($action != 'add_price' && $action != 'update_price') {
908  $parameters = array();
909  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
910  if (empty($reshook)) {
911  if ($usercancreate) {
912  print '<a class="butAction" href="'.DOL_URL_ROOT.'/product/fournisseurs.php?id='.$object->id.'&action=add_price&token='.newToken().'">';
913  print $langs->trans("AddSupplierPrice").'</a>';
914  }
915  }
916  }
917 
918  print "</div>\n";
919 
920  if ($user->hasRight("fournisseur", "read")) { // Duplicate ? this check is already in the head of this file
921  $param = '';
922  if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
923  $param .= '&contextpage='.urlencode($contextpage);
924  }
925  if ($limit > 0 && $limit != $conf->liste_limit) {
926  $param .= '&limit='.urlencode($limit);
927  }
928  $param .= '&ref='.urlencode($object->ref);
929 
930  $product_fourn = new ProductFournisseur($db);
931  $product_fourn_list = $product_fourn->list_product_fournisseur_price($object->id, $sortfield, $sortorder, $limit, $offset);
932  $product_fourn_list_all = $product_fourn->list_product_fournisseur_price($object->id, $sortfield, $sortorder, 0, 0);
933  $nbtotalofrecords = count($product_fourn_list_all);
934  $num = count($product_fourn_list);
935  if (($num + ($offset * $limit)) < $nbtotalofrecords) {
936  $num++;
937  }
938 
939  print_barre_liste($langs->trans('SupplierPrices'), $page, $_SERVER['PHP_SELF'], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_accountancy.png', 0, '', '', $limit, 1);
940 
941  // Definition of fields for lists
942  // Some fields are missing because they are not included in the database query
943  $arrayfields = array(
944  'pfp.datec'=>array('label'=>$langs->trans("AppliedPricesFrom"), 'checked'=>1, 'position'=>1),
945  's.nom'=>array('label'=>$langs->trans("Suppliers"), 'checked'=>1, 'position'=>2),
946  'pfp.fk_availability'=>array('label'=>$langs->trans("Availability"), 'enabled' => getDolGlobalInt('FOURN_PRODUCT_AVAILABILITY'), 'checked'=>0, 'position'=>4),
947  'pfp.quantity'=>array('label'=>$langs->trans("QtyMin"), 'checked'=>1, 'position'=>5),
948  'pfp.unitprice'=>array('label'=>$langs->trans("UnitPriceHT"), 'checked'=>1, 'position'=>9),
949  'pfp.multicurrency_unitprice'=>array('label'=>$langs->trans("UnitPriceHTCurrency"), 'enabled' => isModEnabled('multicurrency'), 'checked'=>0, 'position'=>10),
950  'pfp.charges'=>array('label'=>$langs->trans("Charges"), 'enabled' => !empty($conf->global->PRODUCT_CHARGES), 'checked'=>0, 'position'=>11),
951  'pfp.delivery_time_days'=>array('label'=>$langs->trans("NbDaysToDelivery"), 'checked'=>-1, 'position'=>13),
952  'pfp.supplier_reputation'=>array('label'=>$langs->trans("ReputationForThisProduct"), 'checked'=>-1, 'position'=>14),
953  'pfp.fk_barcode_type'=>array('label'=>$langs->trans("BarcodeType"), 'enabled' => isModEnabled('barcode'), 'checked'=>0, 'position'=>15),
954  'pfp.barcode'=>array('label'=>$langs->trans("BarcodeValue"), 'enabled' => isModEnabled('barcode'), 'checked'=>0, 'position'=>16),
955  'pfp.packaging'=>array('label'=>$langs->trans("PackagingForThisProduct"), 'enabled' => getDolGlobalInt('PRODUCT_USE_SUPPLIER_PACKAGING'), 'checked'=>0, 'position'=>17),
956  'pfp.tms'=>array('label'=>$langs->trans("DateModification"), 'enabled' => isModEnabled('barcode'), 'checked'=>1, 'position'=>18),
957  );
958 
959  // fetch optionals attributes and labels
960  $extrafields->fetch_name_optionals_label("product_fournisseur_price");
961  if ($extrafields->attributes["product_fournisseur_price"] && array_key_exists('label', $extrafields->attributes["product_fournisseur_price"])) {
962  $extralabels = $extrafields->attributes["product_fournisseur_price"]['label'];
963 
964  if (!empty($extralabels)) {
965  foreach ($extralabels as $key => $value) {
966  // Show field if not hidden
967  if (!empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
968  $extratitle = $langs->trans($value);
969  $arrayfields['ef.' . $key] = array('label' => $extratitle, 'checked' => 0,
970  'position' => (end($arrayfields)['position'] + 1),
971  'langfile' => $extrafields->attributes["product_fournisseur_price"]['langfile'][$key],
972  'help' => $extrafields->attributes["product_fournisseur_price"]['help'][$key]);
973  }
974  }
975  }
976  }
977 
978  // Selection of new fields
979  include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
980 
981  $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
982  $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
983 
984  print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post" name="formulaire">';
985  print '<input type="hidden" name="token" value="'.newToken().'">';
986  print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
987  print '<input type="hidden" name="action" value="list">';
988  print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
989  print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
990 
991  // Suppliers list title
992  print '<div class="div-table-responsive">';
993  print '<table class="liste centpercent">';
994 
995  $param = "&id=".$object->id;
996 
997  $nbfields = 0;
998 
999  print '<tr class="liste_titre">';
1000  if (!empty($arrayfields['pfp.datec']['checked'])) {
1001  print_liste_field_titre("AppliedPricesFrom", $_SERVER["PHP_SELF"], "pfp.datec", "", $param, "", $sortfield, $sortorder, '', '', 1);
1002  $nbfields++;
1003  }
1004  if (!empty($arrayfields['s.nom']['checked'])) {
1005  print_liste_field_titre("Suppliers", $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder, '', '', 1);
1006  $nbfields++;
1007  }
1008  print_liste_field_titre("SupplierRef", $_SERVER["PHP_SELF"], "", "", $param, "", $sortfield, $sortorder, '', '', 1);
1009  $nbfields++;
1010  if (!empty($arrayfields['pfp.fk_availability']['checked'])) {
1011  print_liste_field_titre("Availability", $_SERVER["PHP_SELF"], "pfp.fk_availability", "", $param, "", $sortfield, $sortorder);
1012  $nbfields++;
1013  }
1014  if (!empty($arrayfields['pfp.quantity']['checked'])) {
1015  print_liste_field_titre("QtyMin", $_SERVER["PHP_SELF"], "pfp.quantity", "", $param, '', $sortfield, $sortorder, 'right ');
1016  $nbfields++;
1017  }
1018  print_liste_field_titre("VATRate", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1019  $nbfields++;
1020  print_liste_field_titre("PriceQtyMinHT", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1021  $nbfields++;
1022  if (isModEnabled("multicurrency")) {
1023  print_liste_field_titre("PriceQtyMinHTCurrency", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1024  $nbfields++;
1025  }
1026  if (!empty($arrayfields['pfp.unitprice']['checked'])) {
1027  print_liste_field_titre("UnitPriceHT", $_SERVER["PHP_SELF"], "pfp.unitprice", "", $param, '', $sortfield, $sortorder, 'right ');
1028  $nbfields++;
1029  }
1030  if (!empty($arrayfields['pfp.multicurrency_unitprice']['checked'])) {
1031  print_liste_field_titre("UnitPriceHTCurrency", $_SERVER["PHP_SELF"], "pfp.multicurrency_unitprice", "", $param, '', $sortfield, $sortorder, 'right ');
1032  $nbfields++;
1033  }
1034  if (isModEnabled("multicurrency")) {
1035  print_liste_field_titre("Currency", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
1036  $nbfields++;
1037  }
1038  if (!empty($arrayfields['pfp.charges']['checked'])) {
1039  print_liste_field_titre("Charges", $_SERVER["PHP_SELF"], "pfp.charges", "", $param, '', $sortfield, $sortorder, 'right ');
1040  $nbfields++;
1041  }
1042  print_liste_field_titre("DiscountQtyMin", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1043  $nbfields++;
1044  if (!empty($arrayfields['pfp.delivery_time_days']['checked'])) {
1045  print_liste_field_titre("NbDaysToDelivery", $_SERVER["PHP_SELF"], "pfp.delivery_time_days", "", $param, '', $sortfield, $sortorder, 'right ');
1046  $nbfields++;
1047  }
1048  if (!empty($arrayfields['pfp.supplier_reputation']['checked'])) {
1049  print_liste_field_titre("ReputationForThisProduct", $_SERVER["PHP_SELF"], "pfp.supplier_reputation", "", $param, '', $sortfield, $sortorder, 'center ');
1050  $nbfields++;
1051  }
1052  if (!empty($arrayfields['pfp.fk_barcode_type']['checked'])) {
1053  print_liste_field_titre("BarcodeType", $_SERVER["PHP_SELF"], "pfp.fk_barcode_type", "", $param, '', $sortfield, $sortorder, 'center ');
1054  $nbfields++;
1055  }
1056  if (!empty($arrayfields['pfp.barcode']['checked'])) {
1057  print_liste_field_titre("BarcodeValue", $_SERVER["PHP_SELF"], "pfp.barcode", "", $param, '', $sortfield, $sortorder, 'center ');
1058  $nbfields++;
1059  }
1060  if (!empty($arrayfields['pfp.packaging']['checked'])) {
1061  print_liste_field_titre("PackagingForThisProduct", $_SERVER["PHP_SELF"], "pfp.packaging", "", $param, 'align="center"', $sortfield, $sortorder);
1062  $nbfields++;
1063  }
1064  if (!empty($arrayfields['pfp.tms']['checked'])) {
1065  print_liste_field_titre("DateModification", $_SERVER["PHP_SELF"], "pfp.tms", "", $param, '', $sortfield, $sortorder, 'right ', '', 1);
1066  $nbfields++;
1067  }
1068 
1069  // fetch optionals attributes and labels
1070  $extrafields->fetch_name_optionals_label("product_fournisseur_price");
1071  if ($extrafields->attributes["product_fournisseur_price"] && array_key_exists('label', $extrafields->attributes["product_fournisseur_price"])) {
1072  $extralabels = $extrafields->attributes["product_fournisseur_price"]['label'];
1073 
1074  if (!empty($extralabels)) {
1075  foreach ($extralabels as $key => $value) {
1076  // Show field if not hidden
1077  if (!empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1078  if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
1079  $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
1080  }
1081  if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
1082  $extratitle = $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
1083  } else {
1084  $extratitle = $langs->trans($value);
1085  }
1086  if (!empty($arrayfields['ef.' . $key]['checked'])) {
1087  print_liste_field_titre($extratitle, $_SERVER["PHP_SELF"], 'ef.' . $key, '', $param, '', $sortfield, $sortorder, 'right ');
1088  $nbfields++;
1089  }
1090  }
1091  }
1092  }
1093  }
1094 
1095  if (is_object($hookmanager)) {
1096  $parameters = array('id_fourn'=>(!empty($id_fourn)?$id_fourn:''), 'prod_id'=>$object->id, 'nbfields'=>$nbfields);
1097  $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action);
1098  }
1099  print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1100  $nbfields++;
1101  print "</tr>\n";
1102 
1103  if (is_array($product_fourn_list)) {
1104  foreach ($product_fourn_list as $productfourn) {
1105  print '<tr class="oddeven">';
1106 
1107  // Date from
1108  if (!empty($arrayfields['pfp.datec']['checked'])) {
1109  print '<td>'.dol_print_date(($productfourn->fourn_date_creation ? $productfourn->fourn_date_creation : $productfourn->date_creation), 'dayhour', 'tzuserrel').'</td>';
1110  }
1111 
1112  // Supplier
1113  if (!empty($arrayfields['s.nom']['checked'])) {
1114  print '<td class="tdoverflowmax150">'.$productfourn->getSocNomUrl(1, 'supplier').'</td>';
1115  }
1116 
1117  // Supplier ref
1118  if ($usercancreate) { // change required right here
1119  print '<td class="tdoverflowmax150">'.$productfourn->getNomUrl().'</td>';
1120  } else {
1121  print '<td class="tdoverflowmax150">'.dol_escape_htmltag($productfourn->fourn_ref).'</td>';
1122  }
1123 
1124  // Availability
1125  if (!empty($arrayfields['pfp.fk_availability']['checked'])) {
1126  $form->load_cache_availability();
1127  $availability = $form->cache_availability[$productfourn->fk_availability]['label'];
1128  print '<td class="left">'.$availability.'</td>';
1129  }
1130 
1131  // Quantity
1132  if (!empty($arrayfields['pfp.quantity']['checked'])) {
1133  print '<td class="right">';
1134  print $productfourn->fourn_qty;
1135  // Units
1136  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
1137  $unit = $object->getLabelOfUnit();
1138  if ($unit !== '') {
1139  print '&nbsp;&nbsp;'.$langs->trans($unit);
1140  }
1141  }
1142  print '</td>';
1143  }
1144 
1145  // VAT rate
1146  print '<td class="right">';
1147  print vatrate($productfourn->fourn_tva_tx, true);
1148  print '</td>';
1149 
1150  // Price for the quantity
1151  print '<td class="right">';
1152  print $productfourn->fourn_price ? '<span class="amount">'.price($productfourn->fourn_price).'</span>' : "";
1153  print '</td>';
1154 
1155  if (isModEnabled("multicurrency")) {
1156  // Price for the quantity in currency
1157  print '<td class="right">';
1158  print $productfourn->fourn_multicurrency_price ? '<span class="amount">'.price($productfourn->fourn_multicurrency_price).'</span>' : "";
1159  print '</td>';
1160  }
1161 
1162  // Unit price
1163  if (!empty($arrayfields['pfp.unitprice']['checked'])) {
1164  print '<td class="right">';
1165  print price($productfourn->fourn_unitprice);
1166  //print $objp->unitprice? price($objp->unitprice) : ($objp->quantity?price($objp->price/$objp->quantity):"&nbsp;");
1167  print '</td>';
1168  }
1169 
1170  // Unit price in currency
1171  if (!empty($arrayfields['pfp.multicurrency_unitprice']['checked'])) {
1172  print '<td class="right">';
1173  print price($productfourn->fourn_multicurrency_unitprice);
1174  print '</td>';
1175  }
1176 
1177  // Currency
1178  if (isModEnabled("multicurrency")) {
1179  print '<td class="right nowraponall">';
1180  print $productfourn->fourn_multicurrency_code ? currency_name($productfourn->fourn_multicurrency_code) : '';
1181  print '</td>';
1182  }
1183 
1184  // Charges
1185  if (!empty($arrayfields['pfp.charges']['checked'])) {
1186  print '<td class="right">';
1187  print price($productfourn->fourn_charges);
1188  print '</td>';
1189  }
1190 
1191  // Discount
1192  print '<td class="right">';
1193  print price2num($productfourn->fourn_remise_percent).'%';
1194  print '</td>';
1195 
1196  // Delivery delay
1197  if (!empty($arrayfields['pfp.delivery_time_days']['checked'])) {
1198  print '<td class="right">';
1199  print $productfourn->delivery_time_days;
1200  print '</td>';
1201  }
1202 
1203  // Reputation
1204  if (!empty($arrayfields['pfp.supplier_reputation']['checked'])) {
1205  print '<td class="center">';
1206  if (!empty($productfourn->supplier_reputation) && !empty($object->reputations[$productfourn->supplier_reputation])) {
1207  print $object->reputations[$productfourn->supplier_reputation];
1208  }
1209  print'</td>';
1210  }
1211 
1212  // Barcode type
1213  if (!empty($arrayfields['pfp.fk_barcode_type']['checked'])) {
1214  print '<td class="center">';
1215  $productfourn->barcode_type = !empty($productfourn->supplier_fk_barcode_type) ? $productfourn->supplier_fk_barcode_type : 0;
1216  $productfourn->fetch_barcode();
1217  print $productfourn->barcode_type_label ? $productfourn->barcode_type_label : ($productfourn->supplier_barcode ? '<div class="warning">'.$langs->trans("SetDefaultBarcodeType").'<div>' : '');
1218  print '</td>';
1219  }
1220 
1221  // Barcode
1222  if (!empty($arrayfields['pfp.barcode']['checked'])) {
1223  print '<td align="right">';
1224  print $productfourn->supplier_barcode;
1225  print '</td>';
1226  }
1227 
1228  // Packaging
1229  if (!empty($arrayfields['pfp.packaging']['checked'])) {
1230  print '<td align="center">';
1231  print price2num($productfourn->packaging);
1232  print '</td>';
1233  }
1234 
1235  // Date modification
1236  if (!empty($arrayfields['pfp.tms']['checked'])) {
1237  print '<td class="right nowraponall">';
1238  print dol_print_date(($productfourn->fourn_date_modification ? $productfourn->fourn_date_modification : $productfourn->date_modification), "dayhour");
1239  print '</td>';
1240  }
1241 
1242  // Extrafields
1243  if (!empty($extralabels)) {
1244  $sql = "SELECT";
1245  $sql .= " fk_object";
1246  foreach ($extralabels as $key => $value) {
1247  $sql .= ", ".$key;
1248  }
1249  $sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
1250  $sql .= " WHERE fk_object = ".((int) $productfourn->product_fourn_price_id);
1251  $resql = $db->query($sql);
1252  if ($resql) {
1253  if ($db->num_rows($resql) != 1) {
1254  foreach ($extralabels as $key => $value) {
1255  if (!empty($arrayfields['ef.'.$key]['checked']) && !empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1256  print "<td></td>";
1257  }
1258  }
1259  } else {
1260  $obj = $db->fetch_object($resql);
1261  foreach ($extralabels as $key => $value) {
1262  if (!empty($arrayfields['ef.'.$key]['checked']) && !empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1263  print '<td align="right">'.$extrafields->showOutputField($key, $obj->{$key}, '', 'product_fournisseur_price')."</td>";
1264  }
1265  }
1266  }
1267  $db->free($resql);
1268  }
1269  }
1270 
1271  if (is_object($hookmanager)) {
1272  $parameters = array('id_pfp'=>$productfourn->product_fourn_price_id, 'id_fourn'=>(!empty($id_fourn)?$id_fourn:''), 'prod_id'=>$object->id);
1273  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action);
1274  }
1275 
1276  // Modify-Remove
1277  print '<td class="center nowraponall">';
1278 
1279  if ($usercancreate) {
1280  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>";
1281  print ' &nbsp; ';
1282  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>';
1283  }
1284 
1285  print '</td>';
1286 
1287  print '</tr>';
1288  }
1289 
1290  if (empty($product_fourn_list)) {
1291  print '<tr><td colspan="'.$nbfields.'"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
1292  }
1293  } else {
1294  dol_print_error($db);
1295  }
1296 
1297  print '</table>';
1298  print '</div>';
1299  print '</form>';
1300  }
1301  }
1302  }
1303 } else {
1304  print $langs->trans("ErrorUnknown");
1305 }
1306 
1307 // End of page
1308 llxFooter();
1309 $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.
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.