dolibarr  x.y.z
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  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program. If not, see <https://www.gnu.org/licenses/>.
27  */
28 
35 // Load Dolibarr environment
36 require '../main.inc.php';
37 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
38 require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
39 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
40 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
41 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
42 require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_expression.class.php';
43 require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
44 if (isModEnabled('barcode')) {
45  dol_include_once('/core/class/html.formbarcode.class.php');
46 }
47 // Load translation files required by the page
48 $langs->loadLangs(array('products', 'suppliers', 'bills', 'margins', 'stocks'));
49 
50 $id = GETPOST('id', 'int');
51 $ref = GETPOST('ref', 'alpha');
52 $rowid = GETPOST('rowid', 'int');
53 $action = GETPOST('action', 'aZ09');
54 $cancel = GETPOST('cancel', 'alpha');
55 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'pricesuppliercard';
56 
57 $socid = GETPOST('socid', 'int');
58 $cost_price = price2num(GETPOST('cost_price', 'alpha'), '', 2);
59 $pmp = price2num(GETPOST('pmp', 'alpha'), '', 2);
60 
61 $backtopage = GETPOST('backtopage', 'alpha');
62 $error = 0;
63 
64 $extrafields = new ExtraFields($db);
65 
66 // If socid provided by ajax company selector
67 if (GETPOST('search_fourn_id', 'int')) {
68  $_GET['id_fourn'] = GETPOST('search_fourn_id', 'int');
69  $_POST['id_fourn'] = GETPOST('search_fourn_id', 'int');
70 }
71 
72 // Security check
73 $fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : ''));
74 $fieldtype = (!empty($ref) ? 'ref' : 'rowid');
75 if ($user->socid) {
76  $socid = $user->socid;
77 }
78 
79 if (empty($user->rights->fournisseur->lire) && (empty($conf->margin->enabled) && !$user->hasRight("margin", "liretous"))) {
81 }
82 
83 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
84 $sortfield = GETPOST('sortfield', 'aZ09comma');
85 $sortorder = GETPOST('sortorder', 'aZ09comma');
86 $page = (GETPOST("page", 'int') ?GETPOST("page", 'int') : 0);
87 if (empty($page) || $page == -1) {
88  $page = 0;
89 } // If $page is not defined, or '' or -1
90 $offset = $limit * $page;
91 $pageprev = $page - 1;
92 $pagenext = $page + 1;
93 if (!$sortfield) {
94  $sortfield = "s.nom";
95 }
96 if (!$sortorder) {
97  $sortorder = "ASC";
98 }
99 
100 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
101 $hookmanager->initHooks(array('pricesuppliercard', 'globalcard'));
102 
103 $object = new ProductFournisseur($db);
104 if ($id > 0 || $ref) {
105  $object->fetch($id, $ref);
106 }
107 
108 $usercanread = (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->lire) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->lire));
109 $usercancreate = (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->creer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->creer));
110 
111 if ($object->id > 0) {
112  if ($object->type == $object::TYPE_PRODUCT) {
113  restrictedArea($user, 'produit', $object->id, 'product&product', '', '');
114  }
115  if ($object->type == $object::TYPE_SERVICE) {
116  restrictedArea($user, 'service', $object->id, 'product&product', '', '');
117  }
118 } else {
119  restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype);
120 }
121 
122 
123 /*
124  * Actions
125  */
126 
127 if ($cancel) {
128  $action = '';
129 }
130 
131 $parameters = array('socid'=>$socid, 'id_prod'=>$id);
132 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
133 if ($reshook < 0) {
134  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
135 }
136 
137 if (empty($reshook)) {
138  if ($action == 'setcost_price') {
139  if ($id) {
140  $result = $object->fetch($id);
141  $object->cost_price = price2num($cost_price);
142  $result = $object->update($object->id, $user);
143  if ($result > 0) {
144  setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
145  $action = '';
146  } else {
147  $error++;
148  setEventMessages($object->error, $object->errors, 'errors');
149  }
150  }
151  }
152  if ($action == 'setpmp') {
153  if ($id) {
154  $result = $object->fetch($id);
155  $object->pmp = price2num($pmp);
156  $sql = "UPDATE ".MAIN_DB_PREFIX."product SET pmp = ".((float) $object->pmp)." WHERE rowid = ".((int) $id);
157  $resql = $db->query($sql);
158  //$result = $object->update($object->id, $user);
159  if ($resql) {
160  setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
161  $action = '';
162  } else {
163  $error++;
164  setEventMessages($object->error, $object->errors, 'errors');
165  }
166  }
167  }
168 
169  if ($action == 'confirm_remove_pf') {
170  if ($rowid) { // id of product supplier price to remove
171  $action = '';
172  $result = $object->remove_product_fournisseur_price($rowid);
173  if ($result > 0) {
174  $db->query("DELETE FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields WHERE fk_object = ".((int) $rowid));
175  setEventMessages($langs->trans("PriceRemoved"), null, 'mesgs');
176  } else {
177  $error++;
178  setEventMessages($object->error, $object->errors, 'errors');
179  }
180  }
181  }
182 
183  if ($action == 'save_price') {
184  $id_fourn = GETPOST("id_fourn");
185  if (empty($id_fourn)) {
186  $id_fourn = GETPOST("search_id_fourn");
187  }
188  $ref_fourn = GETPOST("ref_fourn");
189  if (empty($ref_fourn)) {
190  $ref_fourn = GETPOST("search_ref_fourn");
191  }
192  $ref_fourn_old = GETPOST("ref_fourn_old");
193  if (empty($ref_fourn_old)) {
194  $ref_fourn_old = $ref_fourn;
195  }
196  $quantity = price2num(GETPOST("qty", 'alphanohtml'), 'MS');
197  $remise_percent = price2num(GETPOST('remise_percent', 'alpha'));
198 
199  $npr = preg_match('/\*/', GETPOST('tva_tx', 'alpha')) ? 1 : 0;
200  $tva_tx = str_replace('*', '', GETPOST('tva_tx', 'alpha'));
201  if (!preg_match('/\‍((.*)\‍)/', $tva_tx)) {
202  $tva_tx = price2num($tva_tx);
203  }
204 
205  $price_expression = GETPOST('eid', 'int') ? GETPOST('eid', 'int') : ''; // Discard expression if not in expression mode
206  $delivery_time_days = GETPOST('delivery_time_days', 'int') ? GETPOST('delivery_time_days', 'int') : '';
207  $supplier_reputation = GETPOST('supplier_reputation');
208  $supplier_description = GETPOST('supplier_description', 'restricthtml');
209  $barcode = GETPOST('barcode', 'alpha');
210  $fk_barcode_type = GETPOST('fk_barcode_type', 'int');
211  $packaging = price2num(GETPOST("packaging", 'alphanohtml'), 'MS');
212 
213  if ($tva_tx == '') {
214  $error++;
215  $langs->load("errors");
216  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("VATRateForSupplierProduct")), null, 'errors');
217  }
218  if (!is_numeric($tva_tx)) {
219  $error++;
220  $langs->load("errors");
221  setEventMessages($langs->trans("ErrorFieldMustBeANumeric", $langs->transnoentities("VATRateForSupplierProduct")), null, 'errors');
222  }
223  if (empty($quantity)) {
224  $error++;
225  $langs->load("errors");
226  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Qty")), null, 'errors');
227  }
228  if (empty($ref_fourn)) {
229  $error++;
230  $langs->load("errors");
231  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("RefSupplier")), null, 'errors');
232  }
233  if ($id_fourn <= 0) {
234  $error++;
235  $langs->load("errors");
236  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Supplier")), null, 'errors');
237  }
238  if (price2num(GETPOST("price")) < 0 || GETPOST("price") == '') {
239  if ($price_expression === '') { // Return error of missing price only if price_expression not set
240  $error++;
241  $langs->load("errors");
242  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Price")), null, 'errors');
243  } else {
244  $_POST["price"] = 0;
245  }
246  }
247  if (isModEnabled("multicurrency")) {
248  if (!GETPOST("multicurrency_code")) {
249  $error++;
250  $langs->load("errors");
251  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Currency")), null, 'errors');
252  }
253  if (price2num(GETPOST("multicurrency_tx")) <= 0 || GETPOST("multicurrency_tx") == '') {
254  $error++;
255  $langs->load("errors");
256  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("CurrencyRate")), null, 'errors');
257  }
258  if (price2num(GETPOST("multicurrency_price")) < 0 || GETPOST("multicurrency_price") == '') {
259  $error++;
260  $langs->load("errors");
261  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("PriceCurrency")), null, 'errors');
262  }
263  }
264 
265  if (!$error) {
266  $db->begin();
267 
268  if (!$error) {
269  $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
270  if ($ret == -3) {
271  $error++;
272 
273  $tmpobject = new Product($db);
274  $tmpobject->fetch($object->product_id_already_linked);
275  $productLink = $tmpobject->getNomUrl(1, 'supplier');
276 
277  $texttoshow = $langs->trans("ReferenceSupplierIsAlreadyAssociatedWithAProduct", '{s1}');
278  $texttoshow = str_replace('{s1}', $productLink, $texttoshow);
279  setEventMessages($texttoshow, null, 'errors');
280  } elseif ($ret < 0) {
281  $error++;
282  setEventMessages($object->error, $object->errors, 'errors');
283  }
284  }
285 
286  if (!$error) {
287  $supplier = new Fournisseur($db);
288  $result = $supplier->fetch($id_fourn);
289  if (GETPOSTISSET('ref_fourn_price_id')) {
290  $object->fetch_product_fournisseur_price(GETPOST('ref_fourn_price_id', 'int'));
291  }
292  $extralabels = $extrafields->fetch_name_optionals_label("product_fournisseur_price");
293  $extrafield_values = $extrafields->getOptionalsFromPost("product_fournisseur_price");
294 
295  $newprice = price2num(GETPOST("price", "alpha"));
296 
297  if (empty($packaging)) {
298  $packaging = 1;
299  }
300  /* We can have a puchase ref that need to buy 100 min for a given price and with a packaging of 50.
301  if ($packaging < $quantity) {
302  $packaging = $quantity;
303  }*/
304  $object->packaging = $packaging;
305 
306  if (isModEnabled("multicurrency")) {
307  $multicurrency_tx = price2num(GETPOST("multicurrency_tx", 'alpha'));
308  $multicurrency_price = price2num(GETPOST("multicurrency_price", 'alpha'));
309  $multicurrency_code = GETPOST("multicurrency_code", 'alpha');
310 
311  $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);
312  } else {
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(), '', 0, 'HT', 1, '', $supplier_description, $barcode, $fk_barcode_type, $extrafield_values);
314  }
315  if ($ret < 0) {
316  $error++;
317  setEventMessages($object->error, $object->errors, 'errors');
318  } else {
319  if (isModEnabled('dynamicprices') && $price_expression !== '') {
320  //Check the expression validity by parsing it
321  require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
322  $priceparser = new PriceParser($db);
323  $object->fk_supplier_price_expression = $price_expression;
324  $price_result = $priceparser->parseProductSupplier($object);
325  if ($price_result < 0) { //Expression is not valid
326  $error++;
327  setEventMessages($priceparser->translatedError(), null, 'errors');
328  }
329  }
330  if (!$error && isModEnabled('dynamicprices')) {
331  //Set the price expression for this supplier price
332  $ret = $object->setSupplierPriceExpression($price_expression);
333  if ($ret < 0) {
334  $error++;
335  setEventMessages($object->error, $object->errors, 'errors');
336  }
337  }
338  }
339  }
340 
341  if (!$error) {
342  $db->commit();
343  $action = '';
344  } else {
345  $db->rollback();
346  }
347  } else {
348  $action = 'add_price';
349  }
350  }
351 }
352 
353 
354 /*
355  * view
356  */
357 
358 $form = new Form($db);
359 
360 $title = $langs->trans('ProductServiceCard');
361 $helpurl = '';
362 $shortlabel = dol_trunc($object->label, 16);
363 if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) {
364  $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('BuyingPrices');
365  $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos|DE:Modul_Produkte';
366 }
367 if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) {
368  $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('BuyingPrices');
369  $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios|DE:Modul_Lesitungen';
370 }
371 
372 llxHeader('', $title, $helpurl, '', 0, 0, '', '', '', 'classforhorizontalscrolloftabs');
373 
374 if ($id > 0 || $ref) {
375  if ($result) {
376  if ($action == 'ask_remove_pf') {
377  $form = new Form($db);
378  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$id.'&rowid='.$rowid, $langs->trans('DeleteProductBuyPrice'), $langs->trans('ConfirmDeleteProductBuyPrice'), 'confirm_remove_pf', '', 0, 1);
379  echo $formconfirm;
380  }
381 
382  if ($action != 'edit' && $action != 're-edit') {
383  $head = product_prepare_head($object);
384  $titre = $langs->trans("CardProduct".$object->type);
385  $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
386 
387  print dol_get_fiche_head($head, 'suppliers', $titre, -1, $picto);
388 
389  $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
390  $object->next_prev_filter = " fk_product_type = ".$object->type;
391 
392  $shownav = 1;
393  if ($user->socid && !in_array('product', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) {
394  $shownav = 0;
395  }
396 
397  dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
398 
399  print '<div class="fichecenter">';
400 
401  print '<div class="underbanner clearboth"></div>';
402  print '<table class="border tableforfield centpercent">';
403 
404  // Type
405  if (isModEnabled("product") && isModEnabled("service")) {
406  $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service");
407  print '<tr><td class="">';
408  print (empty($conf->global->PRODUCT_DENY_CHANGE_PRODUCT_TYPE)) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type');
409  print '</td><td>';
410  print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat);
411  print '</td></tr>';
412  }
413 
414  // Cost price. Can be used for margin module for option "calculate margin on explicit cost price
415  print '<tr><td>';
416  $textdesc = $langs->trans("CostPriceDescription");
417  $textdesc .= "<br>".$langs->trans("CostPriceUsage");
418  $text = $form->textwithpicto($langs->trans("CostPrice"), $textdesc, 1, 'help', '');
419  print $form->editfieldkey($text, 'cost_price', $object->cost_price, $object, $usercancreate, 'amount:6');
420  print '</td><td>';
421  print $form->editfieldval($text, 'cost_price', $object->cost_price, $object, $usercancreate, 'amount:6');
422  print '</td></tr>';
423 
424  // PMP
425  $usercaneditpmp = 0;
426  if (!empty($conf->global->PRODUCT_CAN_EDIT_WAP)) {
427  $usercaneditpmp = $usercancreate;
428  }
429  print '<tr><td class="titlefieldcreate">';
430  $textdesc = $langs->trans("AverageUnitPricePMPDesc");
431  $text = $form->textwithpicto($langs->trans("AverageUnitPricePMPShort"), $textdesc, 1, 'help', '');
432  print $form->editfieldkey($text, 'pmp', $object->pmp, $object, $usercaneditpmp, 'amount:6');
433  print '</td><td>';
434  print $form->editfieldval($text, 'pmp', ($object->pmp > 0 ? $object->pmp : ''), $object, $usercaneditpmp, 'amount:6');
435  if ($object->pmp > 0) {
436  print ' '.$langs->trans("HT");
437  }
438  /*
439  .$form->textwithpicto($langs->trans("AverageUnitPricePMPShort"), $langs->trans("AverageUnitPricePMPDesc")).'</td>';
440  print '<td>';
441  if ($object->pmp > 0) {
442  print price($object->pmp).' '.$langs->trans("HT");
443  }*/
444  print '</td>';
445  print '</tr>';
446 
447  // Best buying Price
448  print '<tr><td class="titlefieldcreate">'.$langs->trans("BuyingPriceMin").'</td>';
449  print '<td>';
450  $product_fourn = new ProductFournisseur($db);
451  if ($product_fourn->find_min_price_product_fournisseur($object->id) > 0) {
452  if ($product_fourn->product_fourn_price_id > 0) {
453  print $product_fourn->display_price_product_fournisseur();
454  } else {
455  print $langs->trans("NotDefined");
456  }
457  }
458  print '</td></tr>';
459 
460  print '</table>';
461 
462  print '</div>';
463  print '<div style="clear:both"></div>';
464 
465  print dol_get_fiche_end();
466 
467 
468  // Form to add or update a price
469  if (($action == 'add_price' || $action == 'update_price') && $usercancreate) {
470  $langs->load("suppliers");
471 
472  print "<!-- form to add a supplier price -->\n";
473  print '<br>';
474 
475  if ($rowid) {
476  $object->fetch_product_fournisseur_price($rowid, 1); //Ignore the math expression when getting the price
477  print load_fiche_titre($langs->trans("ChangeSupplierPrice"));
478  } else {
479  print load_fiche_titre($langs->trans("AddSupplierPrice"));
480  }
481 
482  print '<form action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="POST">';
483  print '<input type="hidden" name="token" value="'.newToken().'">';
484  print '<input type="hidden" name="action" value="save_price">';
485 
486  print dol_get_fiche_head();
487 
488  print '<table class="border centpercent">';
489 
490  // Supplier
491  print '<tr><td class="titlefield fieldrequired">'.$langs->trans("Supplier").'</td><td>';
492  if ($rowid) {
493  $supplier = new Fournisseur($db);
494  $supplier->fetch($socid);
495  print $supplier->getNomUrl(1);
496  print '<input type="hidden" name="id_fourn" value="'.$socid.'">';
497  print '<input type="hidden" name="ref_fourn_price_id" value="'.$rowid.'">';
498  print '<input type="hidden" name="rowid" value="'.$rowid.'">';
499  print '<input type="hidden" name="socid" value="'.$socid.'">';
500  } else {
501  $events = array();
502  $events[] = array('method' => 'getVatRates', 'url' => dol_buildpath('/core/ajax/vatrates.php', 1), 'htmlname' => 'tva_tx', 'params' => array());
503  print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company(GETPOST("id_fourn", 'alpha'), 'id_fourn', 'fournisseur=1', 'SelectThirdParty', 0, 0, $events);
504 
505  $parameters = array('filtre'=>"fournisseur=1", 'html_name'=>'id_fourn', 'selected'=>GETPOST("id_fourn"), 'showempty'=>1, 'prod_id'=>$object->id);
506  $reshook = $hookmanager->executeHooks('formCreateThirdpartyOptions', $parameters, $object, $action);
507  if (empty($reshook)) {
508  if (empty($form->result)) {
509  print '<a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&type=f&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id.'&action='.$action).'">';
510  print img_picto($langs->trans("CreateDolibarrThirdPartySupplier"), 'add', 'class="marginleftonly"');
511  print '</a>';
512  }
513  }
514  print '<script type="text/javascript">
515  $(document).ready(function () {
516  $("#search_id_fourn").change(load_vat)
517  console.log("Requesting default VAT rate for the supplier...")
518  });
519  function load_vat() {
520  // get soc id
521  let socid = $("#id_fourn")[0].value
522 
523  // load available VAT rates
524  let vat_url = "'.dol_buildpath('/core/ajax/vatrates.php', 1).'"
525  //Make GET request with params
526  let options = "";
527  options += "id=" + socid
528  options += "&htmlname=tva_tx"
529  options += "&action=default" // not defined in vatrates.php, default behavior.
530 
531  var get = $.getJSON(
532  vat_url,
533  options,
534  (data) => {
535  rate_options = $.parseHTML(data.value)
536  rate_options.forEach(opt => {
537  if (opt.selected) {
538  replaceVATWithSupplierValue(opt.value)
539  return
540  }
541  })
542  }
543  );
544 
545  }
546  function replaceVATWithSupplierValue(vat_rate) {
547  console.log("Default VAT rate for the supplier: " + vat_rate + "%")
548  $("[name=\'tva_tx\']")[0].value = vat_rate;
549  }
550  </script>';
551  }
552  print '</td></tr>';
553 
554  // Ref supplier
555  print '<tr><td class="fieldrequired">'.$langs->trans("SupplierRef").'</td><td>';
556  if ($rowid) {
557  print '<input type="hidden" name="ref_fourn_old" value="'.$object->ref_supplier.'">';
558  print '<input class="flat width150" maxlength="128" name="ref_fourn" value="'.$object->ref_supplier.'">';
559  } else {
560  print '<input class="flat width150" maxlength="128" name="ref_fourn" value="'.(GETPOST("ref_fourn") ? GETPOST("ref_fourn") : '').'">';
561  }
562  print '</td>';
563  print '</tr>';
564 
565  // Availability
566  if (getDolGlobalInt('FOURN_PRODUCT_AVAILABILITY')) {
567  $langs->load("propal");
568  print '<tr><td>'.$langs->trans("Availability").'</td><td>';
569  $form->selectAvailabilityDelay($object->fk_availability, "oselDispo", 1);
570  print '</td></tr>'."\n";
571  }
572 
573  // Qty min
574  print '<tr>';
575  print '<td class="fieldrequired">'.$langs->trans("QtyMin").'</td>';
576  print '<td>';
577  $quantity = GETPOSTISSET('qty') ? price2num(GETPOST('qty', 'alphanohtml'), 'MS') : "1";
578  if ($rowid) {
579  print '<input type="hidden" name="qty" value="'.$object->fourn_qty.'">';
580  print $object->fourn_qty;
581  } else {
582  print '<input class="flat" name="qty" size="5" value="'.$quantity.'">';
583  }
584  // Units
585  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
586  $unit = $object->getLabelOfUnit();
587  if ($unit !== '') {
588  print '&nbsp;&nbsp;'.$langs->trans($unit);
589  }
590  }
591  print '</td></tr>';
592 
593  if (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING)) {
594  // Packaging/Conditionnement
595  print '<tr>';
596 
597  print '<td class="fieldrequired">'.$form->textwithpicto($langs->trans("PackagingForThisProduct"), $langs->trans("PackagingForThisProductDesc")).'</td>';
598  print '<td>';
599  $packaging = GETPOSTISSET('packaging') ? price2num(GETPOST('packaging', 'alphanohtml'), 'MS') : ((empty($rowid)) ? "1" : price2num($object->packaging, 'MS'));
600  print '<input class="flat" name="packaging" size="5" value="'.$packaging.'">';
601 
602  // Units
603  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
604  $unit = $object->getLabelOfUnit();
605  if ($unit !== '') {
606  print '&nbsp;&nbsp;'.$langs->trans($unit);
607  }
608  }
609  }
610  // Vat rate
611  $default_vat = '';
612 
613  // We don't have supplier, so we try to guess.
614  // For this we build a fictive supplier with same properties than user but using vat)
615  $mysoc2 = clone $mysoc;
616  $mysoc2->name = 'Fictive seller with same country';
617  $mysoc2->tva_assuj = 1;
618  $default_vat = get_default_tva($mysoc2, $mysoc, $object->id, 0);
619  $default_npr = get_default_npr($mysoc2, $mysoc, $object->id, 0);
620  if (empty($default_vat)) {
621  $default_npr = $default_vat;
622  }
623 
624  print '<tr><td class="fieldrequired">'.$langs->trans("VATRateForSupplierProduct").'</td>';
625  print '<td>';
626  //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
627  if (!empty($rowid)) { // If we have a supplier, it is an update, we must show the vat of current supplier price
628  $tmpproductsupplier = new ProductFournisseur($db);
629  $tmpproductsupplier->fetch_product_fournisseur_price($rowid, 1);
630  $default_vat = $tmpproductsupplier->fourn_tva_tx;
631  $default_npr = $tmpproductsupplier->fourn_tva_npr;
632  } else {
633  if (empty($default_vat)) {
634  $default_vat = $object->tva_tx;
635  }
636  }
637  $vattosuggest = (GETPOSTISSET("tva_tx") ? vatrate(GETPOST("tva_tx")) : ($default_vat != '' ?vatrate($default_vat) : ''));
638  $vattosuggest = preg_replace('/\s*\‍(.*\‍)$/', '', $vattosuggest);
639  print '<input type="text" class="flat" size="5" name="tva_tx" value="'.$vattosuggest.'">';
640  print '</td></tr>';
641 
642  if (isModEnabled('dynamicprices')) { //Only show price mode and expression selector if module is enabled
643  // Price mode selector
644  print '<tr><td class="fieldrequired">'.$langs->trans("PriceMode").'</td><td>';
645  $price_expression = new PriceExpression($db);
646  $price_expression_list = array(0 => $langs->trans("PriceNumeric")); //Put the numeric mode as first option
647  foreach ($price_expression->list_price_expression() as $entry) {
648  $price_expression_list[$entry->id] = $entry->title;
649  }
650  $price_expression_preselection = GETPOST('eid') ? GETPOST('eid') : ($object->fk_supplier_price_expression ? $object->fk_supplier_price_expression : '0');
651  print $form->selectarray('eid', $price_expression_list, $price_expression_preselection);
652  print '&nbsp; <div id="expression_editor" class="button">'.$langs->trans("PriceExpressionEditor").'</div>';
653  print '</td></tr>';
654  // This code hides the numeric price input if is not selected, loads the editor page if editor button is pressed
655  print '<script type="text/javascript">
656  jQuery(document).ready(run);
657  function run() {
658  jQuery("#expression_editor").click(on_click);
659  jQuery("#eid").change(on_change);
660  on_change();
661  }
662  function on_click() {
663  window.location = "'.DOL_URL_ROOT.'/product/dynamic_price/editor.php?id='.$id.'&tab=fournisseurs&eid=" + $("#eid").val();
664  }
665  function on_change() {
666  if ($("#eid").val() == 0) {
667  jQuery("#price_numeric").show();
668  } else {
669  jQuery("#price_numeric").hide();
670  }
671  }
672  </script>';
673  }
674 
675  if (isModEnabled("multicurrency")) {
676  // Currency
677  print '<tr><td class="fieldrequired">'.$langs->trans("Currency").'</td>';
678  print '<td>';
679  $currencycodetouse = GETPOST('multicurrency_code') ? GETPOST('multicurrency_code') : (isset($object->fourn_multicurrency_code) ? $object->fourn_multicurrency_code : '');
680  if (empty($currencycodetouse) && $object->fourn_multicurrency_tx == 1) {
681  $currencycodetouse = $conf->currency;
682  }
683  print $form->selectMultiCurrency($currencycodetouse, "multicurrency_code", 1);
684  print ' &nbsp; &nbsp; '.$langs->trans("CurrencyRate").' ';
685  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 : '')).'">';
686  print '</td>';
687  print '</tr>';
688 
689  // Currency price qty min
690  print '<tr><td class="fieldrequired">'.$form->textwithpicto($langs->trans("PriceQtyMinCurrency"), $langs->transnoentitiesnoconv("WithoutDiscount")).'</td>';
691  $pricesupplierincurrencytouse = (GETPOST('multicurrency_price') ? GETPOST('multicurrency_price') : (isset($object->fourn_multicurrency_price) ? $object->fourn_multicurrency_price : ''));
692  print '<td><input class="flat" name="multicurrency_price" size="8" value="'.price($pricesupplierincurrencytouse).'">';
693  print '&nbsp;';
694  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
695  print '</td></tr>';
696 
697  // Price qty min
698  print '<tr><td class="fieldrequired">'.$form->textwithpicto($langs->trans("PriceQtyMin"), $langs->transnoentitiesnoconv("WithoutDiscount")).'</td>';
699  print '<td><input class="flat" name="disabled_price" size="8" value="">';
700  print '<input type="hidden" name="price" value="">';
701  print '<input type="hidden" name="price_base_type" value="">';
702  print '&nbsp;';
703  print $form->selectPriceBaseType('', "disabled_price_base_type");
704  print '</td></tr>';
705 
706  $currencies = array();
707  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."multicurrency WHERE entity = ".((int) $conf->entity);
708  $resql = $db->query($sql);
709  if ($resql) {
710  $currency = new MultiCurrency($db);
711  while ($obj = $db->fetch_object($resql)) {
712  $currency->fetch($obj->rowid);
713  $currencies[$currency->code] = ((float) $currency->rate->rate);
714  }
715  }
716  $currencies = json_encode($currencies);
717 
718  print <<<END
719  <!-- javascript to autocalculate the minimum price -->
720  <script type="text/javascript">
721  function update_price_from_multicurrency() {
722  console.log("update_price_from_multicurrency");
723  var multicurrency_price = price2numjs($('input[name="multicurrency_price"]').val());
724  var multicurrency_tx = price2numjs($('input[name="multicurrency_tx"]').val());
725  if (multicurrency_tx != 0) {
726  $('input[name="price"]').val(multicurrency_price / multicurrency_tx);
727  $('input[name="disabled_price"]').val(multicurrency_price / multicurrency_tx);
728  } else {
729  $('input[name="price"]').val('');
730  $('input[name="disabled_price"]').val('');
731  }
732  }
733 
734  jQuery(document).ready(function () {
735  $('input[name="disabled_price"]').prop('disabled', true);
736  $('select[name="disabled_price_base_type"]').prop('disabled', true);
737  update_price_from_multicurrency();
738 
739  $('input[name="multicurrency_price"], input[name="multicurrency_tx"]').keyup(function () {
740  update_price_from_multicurrency();
741  });
742  $('input[name="multicurrency_price"], input[name="multicurrency_tx"]').change(function () {
743  update_price_from_multicurrency();
744  });
745  $('input[name="multicurrency_price"], input[name="multicurrency_tx"]').on('paste', function () {
746  update_price_from_multicurrency();
747  });
748 
749  $('select[name="multicurrency_price_base_type"]').change(function () {
750  $('input[name="price_base_type"]').val($(this).val());
751  $('select[name="disabled_price_base_type"]').val($(this).val());
752  });
753 
754  var currencies_array = $currencies;
755  $('select[name="multicurrency_code"]').change(function () {
756  console.log("We change the currency");
757  $('input[name="multicurrency_tx"]').val(currencies_array[$(this).val()]);
758  update_price_from_multicurrency();
759  });
760  });
761  </script>
762 END;
763  } else {
764  // Price qty min
765  print '<tr><td class="fieldrequired">'.$langs->trans("PriceQtyMin").'</td>';
766  print '<td><input class="flat" name="price" size="8" value="'.(GETPOST('price') ? price(GETPOST('price')) : (isset($object->fourn_price) ? price($object->fourn_price) : '')).'">';
767  print '&nbsp;';
768  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
769  print '</td></tr>';
770  }
771 
772  // Discount qty min
773  print '<tr><td>'.$langs->trans("DiscountQtyMin").'</td>';
774  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) : '')).'"> %';
775  print '</td>';
776  print '</tr>';
777 
778  // Delivery delay in days
779  print '<tr>';
780  print '<td>'.$langs->trans('NbDaysToDelivery').'</td>';
781  print '<td><input class="flat" name="delivery_time_days" size="4" value="'.($rowid ? $object->delivery_time_days : '').'">&nbsp;'.$langs->trans('days').'</td>';
782  print '</tr>';
783 
784  // Reputation
785  print '<tr><td>'.$langs->trans("ReferenceReputation").'</td><td>';
786  echo $form->selectarray('supplier_reputation', $object->reputations, !empty($supplier_reputation) ? $supplier_reputation : $object->supplier_reputation);
787  print '</td></tr>';
788 
789  // Barcode
790  if (isModEnabled('barcode')) {
791  $formbarcode = new FormBarCode($db);
792 
793  // Barcode type
794  print '<tr>';
795  print '<td>'.$langs->trans('GencodBuyPrice').'</td>';
796  print '<td>';
797  print img_picto('', 'barcode', 'class="pictofixedwidth"');
798  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);
799  print ' <input class="flat" name="barcode" value="'.(GETPOSTISSET('barcode') ? GETPOST('barcode') : ($rowid ? $object->supplier_barcode : '')).'"></td>';
800  print '</tr>';
801  }
802 
803  // Option to define a transport cost on supplier price
804  if (!empty($conf->global->PRODUCT_CHARGES)) {
805  if (isModEnabled('margin')) {
806  print '<tr>';
807  print '<td>'.$langs->trans("Charges").'</td>';
808  print '<td><input class="flat width75" name="charges" value="'.(GETPOST('charges') ? price(GETPOST('charges')) : (isset($object->fourn_charges) ? price($object->fourn_charges) : '')).'">';
809  print '</td>';
810  print '</tr>';
811  }
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.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  print_liste_field_titre("DiscountQtyMin", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1039  $nbfields++;
1040  if (!empty($arrayfields['pfp.delivery_time_days']['checked'])) {
1041  print_liste_field_titre("NbDaysToDelivery", $_SERVER["PHP_SELF"], "pfp.delivery_time_days", "", $param, '', $sortfield, $sortorder, 'right ');
1042  $nbfields++;
1043  }
1044  if (!empty($arrayfields['pfp.supplier_reputation']['checked'])) {
1045  print_liste_field_titre("ReputationForThisProduct", $_SERVER["PHP_SELF"], "pfp.supplier_reputation", "", $param, '', $sortfield, $sortorder, 'center ');
1046  $nbfields++;
1047  }
1048  if (!empty($arrayfields['pfp.fk_barcode_type']['checked'])) {
1049  print_liste_field_titre("BarcodeType", $_SERVER["PHP_SELF"], "pfp.fk_barcode_type", "", $param, '', $sortfield, $sortorder, 'center ');
1050  $nbfields++;
1051  }
1052  if (!empty($arrayfields['pfp.barcode']['checked'])) {
1053  print_liste_field_titre("BarcodeValue", $_SERVER["PHP_SELF"], "pfp.barcode", "", $param, '', $sortfield, $sortorder, 'center ');
1054  $nbfields++;
1055  }
1056  if (!empty($arrayfields['pfp.packaging']['checked'])) {
1057  print_liste_field_titre("PackagingForThisProduct", $_SERVER["PHP_SELF"], "pfp.packaging", "", $param, 'align="center"', $sortfield, $sortorder);
1058  $nbfields++;
1059  }
1060  if (!empty($arrayfields['pfp.tms']['checked'])) {
1061  print_liste_field_titre("DateModification", $_SERVER["PHP_SELF"], "pfp.tms", "", $param, '', $sortfield, $sortorder, 'right ', '', 1);
1062  $nbfields++;
1063  }
1064 
1065  // fetch optionals attributes and labels
1066  $extrafields->fetch_name_optionals_label("product_fournisseur_price");
1067  if ($extrafields->attributes["product_fournisseur_price"] && array_key_exists('label', $extrafields->attributes["product_fournisseur_price"])) {
1068  $extralabels = $extrafields->attributes["product_fournisseur_price"]['label'];
1069 
1070  if (!empty($extralabels)) {
1071  foreach ($extralabels as $key => $value) {
1072  // Show field if not hidden
1073  if (!empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1074  if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
1075  $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
1076  }
1077  if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
1078  $extratitle = $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
1079  } else {
1080  $extratitle = $langs->trans($value);
1081  }
1082  if (!empty($arrayfields['ef.' . $key]['checked'])) {
1083  print_liste_field_titre($extratitle, $_SERVER["PHP_SELF"], 'ef.' . $key, '', $param, '', $sortfield, $sortorder, 'right ');
1084  $nbfields++;
1085  }
1086  }
1087  }
1088  }
1089  }
1090 
1091  if (is_object($hookmanager)) {
1092  $parameters = array('id_fourn'=>(!empty($id_fourn)?$id_fourn:''), 'prod_id'=>$object->id, 'nbfields'=>$nbfields);
1093  $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action);
1094  }
1095  print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1096  $nbfields++;
1097  print "</tr>\n";
1098 
1099  if (is_array($product_fourn_list)) {
1100  foreach ($product_fourn_list as $productfourn) {
1101  print '<tr class="oddeven">';
1102 
1103  // Date from
1104  if (!empty($arrayfields['pfp.datec']['checked'])) {
1105  print '<td>'.dol_print_date(($productfourn->fourn_date_creation ? $productfourn->fourn_date_creation : $productfourn->date_creation), 'dayhour').'</td>';
1106  }
1107 
1108  // Supplier
1109  if (!empty($arrayfields['s.nom']['checked'])) {
1110  print '<td class="tdoverflowmax150">'.$productfourn->getSocNomUrl(1, 'supplier').'</td>';
1111  }
1112 
1113  // Supplier ref
1114  if ($usercancreate) { // change required right here
1115  print '<td class="tdoverflowmax150">'.$productfourn->getNomUrl().'</td>';
1116  } else {
1117  print '<td class="tdoverflowmax150">'.dol_escape_htmltag($productfourn->fourn_ref).'</td>';
1118  }
1119 
1120  // Availability
1121  if (!empty($arrayfields['pfp.fk_availability']['checked'])) {
1122  $form->load_cache_availability();
1123  $availability = $form->cache_availability[$productfourn->fk_availability]['label'];
1124  print '<td class="left">'.$availability.'</td>';
1125  }
1126 
1127  // Quantity
1128  if (!empty($arrayfields['pfp.quantity']['checked'])) {
1129  print '<td class="right">';
1130  print $productfourn->fourn_qty;
1131  // Units
1132  if (!empty($conf->global->PRODUCT_USE_UNITS)) {
1133  $unit = $object->getLabelOfUnit();
1134  if ($unit !== '') {
1135  print '&nbsp;&nbsp;'.$langs->trans($unit);
1136  }
1137  }
1138  print '</td>';
1139  }
1140 
1141  // VAT rate
1142  print '<td class="right">';
1143  print vatrate($productfourn->fourn_tva_tx, true);
1144  print '</td>';
1145 
1146  // Price for the quantity
1147  print '<td class="right">';
1148  print $productfourn->fourn_price ? '<span class="amount">'.price($productfourn->fourn_price).'</span>' : "";
1149  print '</td>';
1150 
1151  if (isModEnabled("multicurrency")) {
1152  // Price for the quantity in currency
1153  print '<td class="right">';
1154  print $productfourn->fourn_multicurrency_price ? '<span class="amount">'.price($productfourn->fourn_multicurrency_price).'</span>' : "";
1155  print '</td>';
1156  }
1157 
1158  // Unit price
1159  if (!empty($arrayfields['pfp.unitprice']['checked'])) {
1160  print '<td class="right">';
1161  print price($productfourn->fourn_unitprice);
1162  //print $objp->unitprice? price($objp->unitprice) : ($objp->quantity?price($objp->price/$objp->quantity):"&nbsp;");
1163  print '</td>';
1164  }
1165 
1166  // Unit price in currency
1167  if (!empty($arrayfields['pfp.multicurrency_unitprice']['checked'])) {
1168  print '<td class="right">';
1169  print price($productfourn->fourn_multicurrency_unitprice);
1170  print '</td>';
1171  }
1172 
1173  // Currency
1174  if (isModEnabled("multicurrency")) {
1175  print '<td class="right nowraponall">';
1176  print $productfourn->fourn_multicurrency_code ? currency_name($productfourn->fourn_multicurrency_code) : '';
1177  print '</td>';
1178  }
1179 
1180  // Discount
1181  print '<td class="right">';
1182  print price2num($productfourn->fourn_remise_percent).'%';
1183  print '</td>';
1184 
1185  // Delivery delay
1186  if (!empty($arrayfields['pfp.delivery_time_days']['checked'])) {
1187  print '<td class="right">';
1188  print $productfourn->delivery_time_days;
1189  print '</td>';
1190  }
1191 
1192  // Reputation
1193  if (!empty($arrayfields['pfp.supplier_reputation']['checked'])) {
1194  print '<td class="center">';
1195  if (!empty($productfourn->supplier_reputation) && !empty($object->reputations[$productfourn->supplier_reputation])) {
1196  print $object->reputations[$productfourn->supplier_reputation];
1197  }
1198  print'</td>';
1199  }
1200 
1201  // Barcode type
1202  if (!empty($arrayfields['pfp.fk_barcode_type']['checked'])) {
1203  print '<td class="center">';
1204  $productfourn->barcode_type = !empty($productfourn->supplier_fk_barcode_type) ? $productfourn->supplier_fk_barcode_type : 0;
1205  $productfourn->fetch_barcode();
1206  print $productfourn->barcode_type_label ? $productfourn->barcode_type_label : ($productfourn->supplier_barcode ? '<div class="warning">'.$langs->trans("SetDefaultBarcodeType").'<div>' : '');
1207  print '</td>';
1208  }
1209 
1210  // Barcode
1211  if (!empty($arrayfields['pfp.barcode']['checked'])) {
1212  print '<td align="right">';
1213  print $productfourn->supplier_barcode;
1214  print '</td>';
1215  }
1216 
1217  // Packaging
1218  if (!empty($arrayfields['pfp.packaging']['checked'])) {
1219  print '<td align="center">';
1220  print price2num($productfourn->packaging);
1221  print '</td>';
1222  }
1223 
1224  // Date modification
1225  if (!empty($arrayfields['pfp.tms']['checked'])) {
1226  print '<td class="right nowraponall">';
1227  print dol_print_date(($productfourn->fourn_date_modification ? $productfourn->fourn_date_modification : $productfourn->date_modification), "dayhour");
1228  print '</td>';
1229  }
1230 
1231  // Extrafields
1232  if (!empty($extralabels)) {
1233  $sql = "SELECT";
1234  $sql .= " fk_object";
1235  foreach ($extralabels as $key => $value) {
1236  $sql .= ", ".$key;
1237  }
1238  $sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
1239  $sql .= " WHERE fk_object = ".((int) $productfourn->product_fourn_price_id);
1240  $resql = $db->query($sql);
1241  if ($resql) {
1242  if ($db->num_rows($resql) != 1) {
1243  foreach ($extralabels as $key => $value) {
1244  if (!empty($arrayfields['ef.'.$key]['checked']) && !empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1245  print "<td></td>";
1246  }
1247  }
1248  } else {
1249  $obj = $db->fetch_object($resql);
1250  foreach ($extralabels as $key => $value) {
1251  if (!empty($arrayfields['ef.'.$key]['checked']) && !empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1252  print '<td align="right">'.$extrafields->showOutputField($key, $obj->{$key}, '', 'product_fournisseur_price')."</td>";
1253  }
1254  }
1255  }
1256  $db->free($resql);
1257  }
1258  }
1259 
1260  if (is_object($hookmanager)) {
1261  $parameters = array('id_pfp'=>$productfourn->product_fourn_price_id, 'id_fourn'=>(!empty($id_fourn)?$id_fourn:''), 'prod_id'=>$object->id);
1262  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action);
1263  }
1264 
1265  // Modify-Remove
1266  print '<td class="center nowraponall">';
1267 
1268  if ($usercancreate) {
1269  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>";
1270  print ' &nbsp; ';
1271  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>';
1272  }
1273 
1274  print '</td>';
1275 
1276  print '</tr>';
1277  }
1278 
1279  if (empty($product_fourn_list)) {
1280  print '<tr><td colspan="'.$nbfields.'"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
1281  }
1282  } else {
1283  dol_print_error($db);
1284  }
1285 
1286  print '</table>';
1287  print '</div>';
1288  print '</form>';
1289  }
1290  }
1291  }
1292 } else {
1293  print $langs->trans("ErrorUnknown");
1294 }
1295 
1296 // End of page
1297 llxFooter();
1298 $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.