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