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