dolibarr 19.0.3
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 (!$user->hasRight('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 //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 = price2num($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') {
158 if ($id) {
159 $result = $object->fetch($id);
160 $object->pmp = price2num($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') {
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') {
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 = GETPOST('eid', 'int') ? GETPOST('eid', 'int') : ''; // Discard expression if not in expression mode
212 $delivery_time_days = GETPOST('delivery_time_days', 'int') ? GETPOST('delivery_time_days', 'int') : '';
213 $supplier_reputation = GETPOST('supplier_reputation');
214 $supplier_description = GETPOST('supplier_description', 'restricthtml');
215 $barcode = GETPOST('barcode', 'alpha');
216 $fk_barcode_type = GETPOST('fk_barcode_type', 'int');
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 ($ref_fourn_price_id > 0) {
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 = price2num(GETPOST("price", "alpha"));
302
303 if (empty($packaging)) {
304 $packaging = 1;
305 }
306 /* We can have a puchase 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 = price2num(GETPOST("multicurrency_tx", 'alpha'));
314 $multicurrency_price = price2num(GETPOST("multicurrency_price", 'alpha'));
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');
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 == 'update_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 $("#search_id_fourn").change(load_vat)
524 console.log("Requesting default VAT rate for the supplier...")
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 += "&action=default" // not defined in vatrates.php, default behavior.
537
538 var get = $.getJSON(
539 vat_url,
540 options,
541 (data) => {
542 rate_options = $.parseHTML(data.value)
543 rate_options.forEach(opt => {
544 if (opt.selected) {
545 replaceVATWithSupplierValue(opt.value);
546 return;
547 }
548 })
549 }
550 );
551
552 }
553 function replaceVATWithSupplierValue(vat_rate) {
554 console.log("Default VAT rate for the supplier: " + vat_rate + "%")
555 $("[name=\'tva_tx\']")[0].value = vat_rate;
556 }
557 </script>';
558 }
559 print '</td></tr>';
560
561 // Ref supplier
562 print '<tr><td class="fieldrequired">'.$langs->trans("SupplierRef").'</td><td>';
563 if ($rowid) {
564 print '<input type="hidden" name="ref_fourn_old" value="'.$object->ref_supplier.'">';
565 print '<input class="flat width150" maxlength="128" name="ref_fourn" value="'.$object->ref_supplier.'">';
566 } else {
567 print '<input class="flat width150" maxlength="128" name="ref_fourn" value="'.(GETPOST("ref_fourn") ? GETPOST("ref_fourn") : '').'">';
568 }
569 print '</td>';
570 print '</tr>';
571
572 // Availability
573 if (getDolGlobalInt('FOURN_PRODUCT_AVAILABILITY')) {
574 $langs->load("propal");
575 print '<tr><td>'.$langs->trans("Availability").'</td><td>';
576 $form->selectAvailabilityDelay($object->fk_availability, "oselDispo", 1);
577 print '</td></tr>'."\n";
578 }
579
580 // Qty min
581 print '<tr>';
582 print '<td class="fieldrequired">'.$langs->trans("QtyMin").'</td>';
583 print '<td>';
584 $quantity = GETPOSTISSET('qty') ? price2num(GETPOST('qty', 'alphanohtml'), 'MS') : "1";
585 if ($rowid) {
586 print '<input type="hidden" name="qty" value="'.$object->fourn_qty.'">';
587 print $object->fourn_qty;
588 } else {
589 print '<input class="flat" name="qty" size="5" value="'.$quantity.'">';
590 }
591 // Units
592 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
593 $unit = $object->getLabelOfUnit();
594 if ($unit !== '') {
595 print '&nbsp;&nbsp;'.$langs->trans($unit);
596 }
597 }
598 print '</td></tr>';
599
600 if (getDolGlobalString('PRODUCT_USE_SUPPLIER_PACKAGING')) {
601 // Packaging/Conditionnement
602 print '<tr>';
603
604 print '<td class="fieldrequired">'.$form->textwithpicto($langs->trans("PackagingForThisProduct"), $langs->trans("PackagingForThisProductDesc")).'</td>';
605 print '<td>';
606 $packaging = GETPOSTISSET('packaging') ? price2num(GETPOST('packaging', 'alphanohtml'), 'MS') : ((empty($rowid)) ? "1" : price2num($object->packaging, 'MS'));
607 print '<input class="flat" name="packaging" size="5" value="'.$packaging.'">';
608
609 // Units
610 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
611 $unit = $object->getLabelOfUnit();
612 if ($unit !== '') {
613 print '&nbsp;&nbsp;'.$langs->trans($unit);
614 }
615 }
616 }
617 // Vat rate
618 $default_vat = '';
619
620 // We don't have supplier, so we try to guess.
621 // For this we build a fictive supplier with same properties than user but using vat)
622 $mysoc2 = clone $mysoc;
623 $mysoc2->name = 'Fictive seller with same country';
624 $mysoc2->tva_assuj = 1;
625 $default_vat = get_default_tva($mysoc2, $mysoc, $object->id, 0);
626 $default_npr = get_default_npr($mysoc2, $mysoc, $object->id, 0);
627 if (empty($default_vat)) {
628 $default_npr = $default_vat;
629 }
630
631 print '<tr><td class="fieldrequired">'.$langs->trans("VATRateForSupplierProduct").'</td>';
632 print '<td>';
633 //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
634 if (!empty($rowid)) { // If we have a supplier, it is an update, we must show the vat of current supplier price
635 $tmpproductsupplier = new ProductFournisseur($db);
636 $tmpproductsupplier->fetch_product_fournisseur_price($rowid, 1);
637 $default_vat = $tmpproductsupplier->fourn_tva_tx;
638 $default_npr = $tmpproductsupplier->fourn_tva_npr;
639 } else {
640 if (empty($default_vat)) {
641 $default_vat = $object->tva_tx;
642 }
643 }
644 $vattosuggest = (GETPOSTISSET("tva_tx") ? vatrate(GETPOST("tva_tx")) : ($default_vat != '' ? vatrate($default_vat) : ''));
645 $vattosuggest = preg_replace('/\s*\‍(.*\‍)$/', '', $vattosuggest);
646 print '<input type="text" class="flat" size="5" name="tva_tx" value="'.$vattosuggest.'">';
647 print '</td></tr>';
648
649 if (isModEnabled('dynamicprices')) { //Only show price mode and expression selector if module is enabled
650 // Price mode selector
651 print '<tr><td class="fieldrequired">'.$langs->trans("PriceMode").'</td><td>';
652 $price_expression = new PriceExpression($db);
653 $price_expression_list = array(0 => $langs->trans("PriceNumeric")); //Put the numeric mode as first option
654 foreach ($price_expression->list_price_expression() as $entry) {
655 $price_expression_list[$entry->id] = $entry->title;
656 }
657 $price_expression_preselection = GETPOST('eid') ? GETPOST('eid') : ($object->fk_supplier_price_expression ? $object->fk_supplier_price_expression : '0');
658 print $form->selectarray('eid', $price_expression_list, $price_expression_preselection);
659 print '&nbsp; <div id="expression_editor" class="button smallpaddingimp">'.$langs->trans("PriceExpressionEditor").'</div>';
660 print '</td></tr>';
661 // This code hides the numeric price input if is not selected, loads the editor page if editor button is pressed
662 print '<script type="text/javascript">
663 jQuery(document).ready(run);
664 function run() {
665 jQuery("#expression_editor").click(on_click);
666 jQuery("#eid").change(on_change);
667 on_change();
668 }
669 function on_click() {
670 window.location = "'.DOL_URL_ROOT.'/product/dynamic_price/editor.php?id='.$id.'&tab=fournisseurs&eid=" + $("#eid").val();
671 }
672 function on_change() {
673 if ($("#eid").val() == 0) {
674 jQuery("#price_numeric").show();
675 } else {
676 jQuery("#price_numeric").hide();
677 }
678 }
679 </script>';
680 }
681
682 if (isModEnabled("multicurrency")) {
683 // Currency
684 print '<tr><td class="fieldrequired">'.$langs->trans("Currency").'</td>';
685 print '<td>';
686 $currencycodetouse = GETPOST('multicurrency_code') ? GETPOST('multicurrency_code') : (isset($object->fourn_multicurrency_code) ? $object->fourn_multicurrency_code : '');
687 if (empty($currencycodetouse) && $object->fourn_multicurrency_tx == 1) {
688 $currencycodetouse = $conf->currency;
689 }
690 print $form->selectMultiCurrency($currencycodetouse, "multicurrency_code", 1);
691 print ' &nbsp; &nbsp; '.$langs->trans("CurrencyRate").' ';
692 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 : '')).'">';
693 print '</td>';
694 print '</tr>';
695
696 // Currency price qty min
697 print '<tr><td class="fieldrequired">'.$form->textwithpicto($langs->trans("PriceQtyMinCurrency"), $langs->transnoentitiesnoconv("WithoutDiscount")).'</td>';
698 $pricesupplierincurrencytouse = (GETPOST('multicurrency_price') ? GETPOST('multicurrency_price') : (isset($object->fourn_multicurrency_price) ? $object->fourn_multicurrency_price : ''));
699 print '<td><input class="flat" name="multicurrency_price" size="8" value="'.price($pricesupplierincurrencytouse).'">';
700 print '&nbsp;';
701 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
702 print '</td></tr>';
703
704 // Price qty min
705 print '<tr><td class="fieldrequired">'.$form->textwithpicto($langs->trans("PriceQtyMin"), $langs->transnoentitiesnoconv("WithoutDiscount")).'</td>';
706 print '<td><input class="flat" name="disabled_price" size="8" value="">';
707 print '<input type="hidden" name="price" value="">';
708 print '<input type="hidden" name="price_base_type" value="">';
709 print '&nbsp;';
710 print $form->selectPriceBaseType('', "disabled_price_base_type");
711 print '</td></tr>';
712
713 $currencies = array();
714 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."multicurrency WHERE entity = ".((int) $conf->entity);
715 $resql = $db->query($sql);
716 if ($resql) {
717 $currency = new MultiCurrency($db);
718 while ($obj = $db->fetch_object($resql)) {
719 $currency->fetch($obj->rowid);
720 $currencies[$currency->code] = ((float) $currency->rate->rate);
721 }
722 }
723 $currencies = json_encode($currencies);
724 print "<!-- javascript to autocalculate the minimum price -->
725 <script type='text/javascript'>
726 function update_price_from_multicurrency() {
727 console.log('update_price_from_multicurrency');
728 var multicurrency_price = price2numjs($('input[name=\"multicurrency_price\"]').val());
729 var multicurrency_tx = price2numjs($('input[name=\"multicurrency_tx\"]').val());
730 if (multicurrency_tx != 0) {
731 $('input[name=\"price\"]').val(multicurrency_price / multicurrency_tx);
732 $('input[name=\"disabled_price\"]').val(multicurrency_price / multicurrency_tx);
733 } else {
734 $('input[name=\"price\"]').val('');
735 $('input[name=\"disabled_price\"]').val('');
736 }
737 }
738
739 jQuery(document).ready(function () {
740 $('input[name=\"disabled_price\"]').prop('disabled', true);
741 $('select[name=\"disabled_price_base_type\"]').prop('disabled', true);
742 update_price_from_multicurrency();
743
744 $('input[name=\"multicurrency_price\"], input[name=\"multicurrency_tx\"]').keyup(function () {
745 update_price_from_multicurrency();
746 });
747 $('input[name=\"multicurrency_price\"], input[name=\"multicurrency_tx\"]').change(function () {
748 update_price_from_multicurrency();
749 });
750 $('input[name=\"multicurrency_price\"], input[name=\"multicurrency_tx\"]').on('paste', function () {
751 update_price_from_multicurrency();
752 });
753
754 $('select[name=\"multicurrency_price_base_type\"]').change(function () {
755 $('input[name=\"price_base_type\"]').val($(this).val());
756 $('select[name=\"disabled_price_base_type\"]').val($(this).val());
757 });
758
759 var currencies_array = $currencies;
760 $('select[name=\"multicurrency_code\"]').change(function () {
761 console.log(\"We change the currency\");
762 $('input[name=\"multicurrency_tx\"]').val(currencies_array[$(this).val()]);
763 update_price_from_multicurrency();
764 });
765 });
766 </script>";
767 } else {
768 // Price qty min
769 print '<tr><td class="fieldrequired">'.$langs->trans("PriceQtyMin").'</td>';
770 print '<td><input class="flat" name="price" size="8" value="'.(GETPOST('price') ? price(GETPOST('price')) : (isset($object->fourn_price) ? price($object->fourn_price) : '')).'">';
771 print '&nbsp;';
772 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
773 print '</td></tr>';
774 }
775
776 // Option to define a transport cost on supplier price
777 if (getDolGlobalString('PRODUCT_CHARGES')) {
778 print '<tr>';
779 print '<td>'.$langs->trans("Charges").'</td>';
780 print '<td><input class="flat" name="charges" size="8" value="'.(GETPOST('charges') ? price(GETPOST('charges')) : (isset($object->fourn_charges) ? price($object->fourn_charges) : '')).'">';
781 print '</td>';
782 print '</tr>';
783 }
784
785 // Discount qty min
786 print '<tr><td>'.$langs->trans("DiscountQtyMin").'</td>';
787 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) : '')).'"> %';
788 print '</td>';
789 print '</tr>';
790
791 // Delivery delay in days
792 print '<tr>';
793 print '<td>'.$langs->trans('NbDaysToDelivery').'</td>';
794 print '<td><input class="flat" name="delivery_time_days" size="4" value="'.($rowid ? $object->delivery_time_days : '').'">&nbsp;'.$langs->trans('days').'</td>';
795 print '</tr>';
796
797 // Reputation
798 print '<tr><td>'.$langs->trans("ReferenceReputation").'</td><td>';
799 echo $form->selectarray('supplier_reputation', $object->reputations, !empty($supplier_reputation) ? $supplier_reputation : $object->supplier_reputation);
800 print '</td></tr>';
801
802 // Barcode
803 if (isModEnabled('barcode')) {
804 $formbarcode = new FormBarCode($db);
805
806 // Barcode type
807 print '<tr>';
808 print '<td>'.$langs->trans('GencodBuyPrice').'</td>';
809 print '<td>';
810 print img_picto('', 'barcode', 'class="pictofixedwidth"');
811 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);
812 print ' <input class="flat" name="barcode" value="'.(GETPOSTISSET('barcode') ? GETPOST('barcode') : ($rowid ? $object->supplier_barcode : '')).'"></td>';
813 print '</tr>';
814 }
815
816 // Product description of the supplier
817 if (getDolGlobalString('PRODUIT_FOURN_TEXTS')) {
818 //WYSIWYG Editor
819 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
820
821 print '<tr>';
822 print '<td>'.$langs->trans('ProductSupplierDescription').'</td>';
823 print '<td>';
824
825 $doleditor = new DolEditor('supplier_description', $object->desc_supplier, '', 160, 'dolibarr_details', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_DETAILS'), ROWS_4, '90%');
826 $doleditor->Create();
827
828 print '</td>';
829 print '</tr>';
830 }
831
832 // Extrafields
833 $extrafields->fetch_name_optionals_label("product_fournisseur_price");
834 $extralabels = !empty($extrafields->attributes["product_fournisseur_price"]['label']) ? $extrafields->attributes["product_fournisseur_price"]['label'] : '';
835 $extrafield_values = $extrafields->getOptionalsFromPost("product_fournisseur_price");
836 if (!empty($extralabels)) {
837 if (empty($rowid)) {
838 foreach ($extralabels as $key => $value) {
839 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))) {
840 if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
841 $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
842 }
843
844 print '<tr><td'.($extrafields->attributes["product_fournisseur_price"]['required'][$key] ? ' class="fieldrequired"' : '').'>';
845 if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
846 print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
847 } else {
848 print $langs->trans($value);
849 }
850 print '</td><td>'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : '', '', '', '', '', 0, 'product_fournisseur_price').'</td></tr>';
851 }
852 }
853 } else {
854 $sql = "SELECT";
855 $sql .= " fk_object";
856 foreach ($extralabels as $key => $value) {
857 $sql .= ", ".$key;
858 }
859 $sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
860 $sql .= " WHERE fk_object = ".((int) $rowid);
861 $resql = $db->query($sql);
862 if ($resql) {
863 $obj = $db->fetch_object($resql);
864 foreach ($extralabels as $key => $value) {
865 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))) {
866 if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
867 $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
868 }
869
870 print '<tr><td'.($extrafields->attributes["product_fournisseur_price"]['required'][$key] ? ' class="fieldrequired"' : '').'>';
871 if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
872 print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
873 } else {
874 print $langs->trans($value);
875 }
876 print '</td><td>'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : $obj->{$key}, '', '', '', '', 0, 'product_fournisseur_price');
877
878 print '</td></tr>';
879 }
880 }
881 $db->free($resql);
882 }
883 }
884 }
885
886 if (is_object($hookmanager)) {
887 $parameters = array('id_fourn'=>!empty($id_fourn) ? $id_fourn : 0, 'prod_id'=>$object->id);
888 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action);
889 print $hookmanager->resPrint;
890 }
891
892 print '</table>';
893
894 print dol_get_fiche_end();
895
896 print '<div class="center">';
897 print '<input class="button button-save" type="submit" value="'.$langs->trans("Save").'">';
898 print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
899 print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
900 print '</div>';
901
902 print '</form>'."\n";
903 }
904
905
906 // Actions buttons
907
908 print '<div class="tabsAction">'."\n";
909
910 if ($action != 'create_price' && $action != 'update_price') {
911 $parameters = array();
912 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
913 if (empty($reshook)) {
914 if ($usercancreate) {
915 print '<a class="butAction" href="'.DOL_URL_ROOT.'/product/fournisseurs.php?id='.((int) $object->id).'&action=create_price&token='.newToken().'">';
916 print $langs->trans("AddSupplierPrice").'</a>';
917 }
918 }
919 }
920
921 print "</div>\n";
922
923 if ($user->hasRight("fournisseur", "read")) { // Duplicate ? this check is already in the head of this file
924 $param = '';
925 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
926 $param .= '&contextpage='.urlencode($contextpage);
927 }
928 if ($limit > 0 && $limit != $conf->liste_limit) {
929 $param .= '&limit='.((int) $limit);
930 }
931 $param .= '&ref='.urlencode($object->ref);
932
933 $product_fourn = new ProductFournisseur($db);
934 $product_fourn_list = $product_fourn->list_product_fournisseur_price($object->id, $sortfield, $sortorder, $limit, $offset);
935 $product_fourn_list_all = $product_fourn->list_product_fournisseur_price($object->id, $sortfield, $sortorder, 0, 0);
936 $nbtotalofrecords = count($product_fourn_list_all);
937 $num = count($product_fourn_list);
938 if (($num + ($offset * $limit)) < $nbtotalofrecords) {
939 $num++;
940 }
941
942 print_barre_liste($langs->trans('SupplierPrices'), $page, $_SERVER['PHP_SELF'], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'title_accountancy.png', 0, '', '', $limit, 1);
943
944 // Definition of fields for lists
945 // Some fields are missing because they are not included in the database query
946 $arrayfields = array(
947 'pfp.datec'=>array('label'=>$langs->trans("AppliedPricesFrom"), 'checked'=>1, 'position'=>1),
948 's.nom'=>array('label'=>$langs->trans("Suppliers"), 'checked'=>1, 'position'=>2),
949 'pfp.fk_availability'=>array('label'=>$langs->trans("Availability"), 'enabled' => getDolGlobalInt('FOURN_PRODUCT_AVAILABILITY'), 'checked'=>0, 'position'=>4),
950 'pfp.quantity'=>array('label'=>$langs->trans("QtyMin"), 'checked'=>1, 'position'=>5),
951 'pfp.unitprice'=>array('label'=>$langs->trans("UnitPriceHT"), 'checked'=>1, 'position'=>9),
952 'pfp.multicurrency_unitprice'=>array('label'=>$langs->trans("UnitPriceHTCurrency"), 'enabled' => isModEnabled('multicurrency'), 'checked'=>0, 'position'=>10),
953 'pfp.charges'=>array('label'=>$langs->trans("Charges"), 'enabled' => getDolGlobalString('PRODUCT_CHARGES'), 'checked'=>0, 'position'=>11),
954 'pfp.delivery_time_days'=>array('label'=>$langs->trans("NbDaysToDelivery"), 'checked'=>-1, 'position'=>13),
955 'pfp.supplier_reputation'=>array('label'=>$langs->trans("ReputationForThisProduct"), 'checked'=>-1, 'position'=>14),
956 'pfp.fk_barcode_type'=>array('label'=>$langs->trans("BarcodeType"), 'enabled' => isModEnabled('barcode'), 'checked'=>0, 'position'=>15),
957 'pfp.barcode'=>array('label'=>$langs->trans("BarcodeValue"), 'enabled' => isModEnabled('barcode'), 'checked'=>0, 'position'=>16),
958 'pfp.packaging'=>array('label'=>$langs->trans("PackagingForThisProduct"), 'enabled' => getDolGlobalInt('PRODUCT_USE_SUPPLIER_PACKAGING'), 'checked'=>0, 'position'=>17),
959 'pfp.status'=>array('label'=>$langs->trans("Status"), 'enabled' => 1, 'checked'=>0, 'position'=>40),
960 'pfp.tms'=>array('label'=>$langs->trans("DateModification"), 'enabled' => isModEnabled('barcode'), 'checked'=>1, 'position'=>50),
961 );
962
963 // fetch optionals attributes and labels
964 $extrafields->fetch_name_optionals_label("product_fournisseur_price");
965 if ($extrafields->attributes["product_fournisseur_price"] && array_key_exists('label', $extrafields->attributes["product_fournisseur_price"])) {
966 $extralabels = $extrafields->attributes["product_fournisseur_price"]['label'];
967
968 if (!empty($extralabels)) {
969 foreach ($extralabels as $key => $value) {
970 // Show field if not hidden
971 if (!empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
972 $extratitle = $langs->trans($value);
973 $arrayfields['ef.' . $key] = array('label' => $extratitle, 'checked' => 0,
974 'position' => (end($arrayfields)['position'] + 1),
975 'langfile' => $extrafields->attributes["product_fournisseur_price"]['langfile'][$key],
976 'help' => $extrafields->attributes["product_fournisseur_price"]['help'][$key]);
977 }
978 }
979 }
980 }
981
982 // Selection of new fields
983 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
984
985 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
986 $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
987
988 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post" name="formulaire">';
989 print '<input type="hidden" name="token" value="'.newToken().'">';
990 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
991 print '<input type="hidden" name="action" value="list">';
992 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
993 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
994
995 // Suppliers list title
996 print '<div class="div-table-responsive">';
997 print '<table class="liste centpercent">';
998
999 $param = "&id=".$object->id;
1000
1001 $nbfields = 0;
1002
1003 print '<tr class="liste_titre">';
1004 if (!empty($arrayfields['pfp.datec']['checked'])) {
1005 print_liste_field_titre("AppliedPricesFrom", $_SERVER["PHP_SELF"], "pfp.datec", "", $param, "", $sortfield, $sortorder, '', '', 1);
1006 $nbfields++;
1007 }
1008 if (!empty($arrayfields['s.nom']['checked'])) {
1009 print_liste_field_titre("Suppliers", $_SERVER["PHP_SELF"], "s.nom", "", $param, "", $sortfield, $sortorder, '', '', 1);
1010 $nbfields++;
1011 }
1012 print_liste_field_titre("SupplierRef", $_SERVER["PHP_SELF"], "", "", $param, "", $sortfield, $sortorder, '', '', 1);
1013 $nbfields++;
1014 if (!empty($arrayfields['pfp.fk_availability']['checked'])) {
1015 print_liste_field_titre("Availability", $_SERVER["PHP_SELF"], "pfp.fk_availability", "", $param, "", $sortfield, $sortorder);
1016 $nbfields++;
1017 }
1018 if (!empty($arrayfields['pfp.quantity']['checked'])) {
1019 print_liste_field_titre("QtyMin", $_SERVER["PHP_SELF"], "pfp.quantity", "", $param, '', $sortfield, $sortorder, 'right ');
1020 $nbfields++;
1021 }
1022 print_liste_field_titre("VATRate", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1023 $nbfields++;
1024 print_liste_field_titre("PriceQtyMinHT", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1025 $nbfields++;
1026 if (isModEnabled("multicurrency")) {
1027 print_liste_field_titre("PriceQtyMinHTCurrency", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1028 $nbfields++;
1029 }
1030 if (!empty($arrayfields['pfp.unitprice']['checked'])) {
1031 print_liste_field_titre("UnitPriceHT", $_SERVER["PHP_SELF"], "pfp.unitprice", "", $param, '', $sortfield, $sortorder, 'right ');
1032 $nbfields++;
1033 }
1034 if (!empty($arrayfields['pfp.multicurrency_unitprice']['checked'])) {
1035 print_liste_field_titre("UnitPriceHTCurrency", $_SERVER["PHP_SELF"], "pfp.multicurrency_unitprice", "", $param, '', $sortfield, $sortorder, 'right ');
1036 $nbfields++;
1037 }
1038 if (isModEnabled("multicurrency")) {
1039 print_liste_field_titre("Currency", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder, 'right ');
1040 $nbfields++;
1041 }
1042 if (!empty($arrayfields['pfp.charges']['checked'])) { // possible only when $conf->global->PRODUCT_CHARGES is set
1043 print_liste_field_titre("Charges", $_SERVER["PHP_SELF"], "pfp.charges", "", $param, '', $sortfield, $sortorder, 'right ');
1044 $nbfields++;
1045 }
1046 print_liste_field_titre("DiscountQtyMin", $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'right ');
1047 $nbfields++;
1048 if (!empty($arrayfields['pfp.delivery_time_days']['checked'])) {
1049 print_liste_field_titre("NbDaysToDelivery", $_SERVER["PHP_SELF"], "pfp.delivery_time_days", "", $param, '', $sortfield, $sortorder, 'right ');
1050 $nbfields++;
1051 }
1052 if (!empty($arrayfields['pfp.supplier_reputation']['checked'])) {
1053 print_liste_field_titre("ReputationForThisProduct", $_SERVER["PHP_SELF"], "pfp.supplier_reputation", "", $param, '', $sortfield, $sortorder, 'center ');
1054 $nbfields++;
1055 }
1056 if (!empty($arrayfields['pfp.fk_barcode_type']['checked'])) {
1057 print_liste_field_titre("BarcodeType", $_SERVER["PHP_SELF"], "pfp.fk_barcode_type", "", $param, '', $sortfield, $sortorder, 'center ');
1058 $nbfields++;
1059 }
1060 if (!empty($arrayfields['pfp.barcode']['checked'])) {
1061 print_liste_field_titre("BarcodeValue", $_SERVER["PHP_SELF"], "pfp.barcode", "", $param, '', $sortfield, $sortorder, 'center ');
1062 $nbfields++;
1063 }
1064 if (!empty($arrayfields['pfp.packaging']['checked'])) {
1065 print_liste_field_titre("PackagingForThisProduct", $_SERVER["PHP_SELF"], "pfp.packaging", "", $param, '', $sortfield, $sortorder, 'center ');
1066 $nbfields++;
1067 }
1068 if (!empty($arrayfields['pfp.status']['checked'])) {
1069 print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "pfp.status", "", $param, '', $sortfield, $sortorder, 'center ', '', 1);
1070 $nbfields++;
1071 }
1072 if (!empty($arrayfields['pfp.tms']['checked'])) {
1073 print_liste_field_titre("DateModification", $_SERVER["PHP_SELF"], "pfp.tms", "", $param, '', $sortfield, $sortorder, 'right ', '', 1);
1074 $nbfields++;
1075 }
1076
1077 // fetch optionals attributes and labels
1078 $extrafields->fetch_name_optionals_label("product_fournisseur_price");
1079 if ($extrafields->attributes["product_fournisseur_price"] && array_key_exists('label', $extrafields->attributes["product_fournisseur_price"])) {
1080 $extralabels = $extrafields->attributes["product_fournisseur_price"]['label'];
1081
1082 if (!empty($extralabels)) {
1083 foreach ($extralabels as $key => $value) {
1084 // Show field if not hidden
1085 if (!empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1086 if (!empty($extrafields->attributes["product_fournisseur_price"]['langfile'][$key])) {
1087 $langs->load($extrafields->attributes["product_fournisseur_price"]['langfile'][$key]);
1088 }
1089 if (!empty($extrafields->attributes["product_fournisseur_price"]['help'][$key])) {
1090 $extratitle = $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_fournisseur_price"]['help'][$key]));
1091 } else {
1092 $extratitle = $langs->trans($value);
1093 }
1094 if (!empty($arrayfields['ef.' . $key]['checked'])) {
1095 print_liste_field_titre($extratitle, $_SERVER["PHP_SELF"], 'ef.' . $key, '', $param, '', $sortfield, $sortorder, 'right ');
1096 $nbfields++;
1097 }
1098 }
1099 }
1100 }
1101 }
1102
1103 if (is_object($hookmanager)) {
1104 $parameters = array('id_fourn'=>(!empty($id_fourn) ? $id_fourn : ''), 'prod_id'=>$object->id, 'nbfields'=>$nbfields);
1105 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action);
1106 }
1107 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1108 $nbfields++;
1109 print "</tr>\n";
1110
1111 if (is_array($product_fourn_list)) {
1112 foreach ($product_fourn_list as $productfourn) {
1113 print '<tr class="oddeven">';
1114
1115 // Date from
1116 if (!empty($arrayfields['pfp.datec']['checked'])) {
1117 print '<td>'.dol_print_date(($productfourn->fourn_date_creation ? $productfourn->fourn_date_creation : $productfourn->date_creation), 'dayhour', 'tzuserrel').'</td>';
1118 }
1119
1120 // Supplier
1121 if (!empty($arrayfields['s.nom']['checked'])) {
1122 print '<td class="tdoverflowmax150">'.$productfourn->getSocNomUrl(1, 'supplier').'</td>';
1123 }
1124
1125 // Supplier ref
1126 if ($usercancreate) { // change required right here
1127 print '<td class="tdoverflowmax150">'.$productfourn->getNomUrl().'</td>';
1128 } else {
1129 print '<td class="tdoverflowmax150">'.dol_escape_htmltag($productfourn->fourn_ref).'</td>';
1130 }
1131
1132 // Availability
1133 if (!empty($arrayfields['pfp.fk_availability']['checked'])) {
1134 $form->load_cache_availability();
1135 $availability = $form->cache_availability[$productfourn->fk_availability]['label'];
1136 print '<td class="left">'.$availability.'</td>';
1137 }
1138
1139 // Quantity
1140 if (!empty($arrayfields['pfp.quantity']['checked'])) {
1141 print '<td class="right">';
1142 print $productfourn->fourn_qty;
1143 // Units
1144 if (getDolGlobalString('PRODUCT_USE_UNITS')) {
1145 $unit = $object->getLabelOfUnit();
1146 if ($unit !== '') {
1147 print '&nbsp;&nbsp;'.$langs->trans($unit);
1148 }
1149 }
1150 print '</td>';
1151 }
1152
1153 // VAT rate
1154 print '<td class="right">';
1155 print vatrate($productfourn->fourn_tva_tx, true);
1156 print '</td>';
1157
1158 // Price for the quantity
1159 print '<td class="right">';
1160 print $productfourn->fourn_price ? '<span class="amount">'.price($productfourn->fourn_price).'</span>' : "";
1161 print '</td>';
1162
1163 if (isModEnabled("multicurrency")) {
1164 // Price for the quantity in currency
1165 print '<td class="right">';
1166 print $productfourn->fourn_multicurrency_price ? '<span class="amount">'.price($productfourn->fourn_multicurrency_price).'</span>' : "";
1167 print '</td>';
1168 }
1169
1170 // Unit price
1171 if (!empty($arrayfields['pfp.unitprice']['checked'])) {
1172 print '<td class="right">';
1173 print price($productfourn->fourn_unitprice);
1174 //print $objp->unitprice? price($objp->unitprice) : ($objp->quantity?price($objp->price/$objp->quantity):"&nbsp;");
1175 print '</td>';
1176 }
1177
1178 // Unit price in currency
1179 if (!empty($arrayfields['pfp.multicurrency_unitprice']['checked'])) {
1180 print '<td class="right">';
1181 print price($productfourn->fourn_multicurrency_unitprice);
1182 print '</td>';
1183 }
1184
1185 // Currency
1186 if (isModEnabled("multicurrency")) {
1187 print '<td class="right nowraponall">';
1188 print $productfourn->fourn_multicurrency_code ? currency_name($productfourn->fourn_multicurrency_code) : '';
1189 print '</td>';
1190 }
1191
1192 // Charges
1193 if (!empty($arrayfields['pfp.charges']['checked'])) { // Possible only when getDolGlobalString('PRODUCT_CHARGES') is set
1194 print '<td class="right">';
1195 print price($productfourn->fourn_charges);
1196 print '</td>';
1197 }
1198
1199 // Discount
1200 print '<td class="right">';
1201 print price2num($productfourn->fourn_remise_percent).'%';
1202 print '</td>';
1203
1204 // Delivery delay
1205 if (!empty($arrayfields['pfp.delivery_time_days']['checked'])) {
1206 print '<td class="right">';
1207 print $productfourn->delivery_time_days;
1208 print '</td>';
1209 }
1210
1211 // Reputation
1212 if (!empty($arrayfields['pfp.supplier_reputation']['checked'])) {
1213 print '<td class="center">';
1214 if (!empty($productfourn->supplier_reputation) && !empty($object->reputations[$productfourn->supplier_reputation])) {
1215 print $object->reputations[$productfourn->supplier_reputation];
1216 }
1217 print'</td>';
1218 }
1219
1220 // Barcode type
1221 if (!empty($arrayfields['pfp.fk_barcode_type']['checked'])) {
1222 print '<td class="center">';
1223 $productfourn->barcode_type = !empty($productfourn->supplier_fk_barcode_type) ? $productfourn->supplier_fk_barcode_type : 0;
1224 $productfourn->fetch_barcode();
1225 print $productfourn->barcode_type_label ? $productfourn->barcode_type_label : ($productfourn->supplier_barcode ? '<div class="warning">'.$langs->trans("SetDefaultBarcodeType").'<div>' : '');
1226 print '</td>';
1227 }
1228
1229 // Barcode
1230 if (!empty($arrayfields['pfp.barcode']['checked'])) {
1231 print '<td class="right">';
1232 print $productfourn->supplier_barcode;
1233 print '</td>';
1234 }
1235
1236 // Packaging
1237 if (!empty($arrayfields['pfp.packaging']['checked'])) {
1238 print '<td class="center">';
1239 print price2num($productfourn->packaging);
1240 print '</td>';
1241 }
1242
1243 // Status
1244 if (!empty($arrayfields['pfp.status']['checked'])) {
1245 print '<td class="center">';
1246 print $productfourn->getLibStatut(3);
1247 print '</td>';
1248 }
1249
1250 // Date modification
1251 if (!empty($arrayfields['pfp.tms']['checked'])) {
1252 print '<td class="right nowraponall">';
1253 print dol_print_date(($productfourn->fourn_date_modification ? $productfourn->fourn_date_modification : $productfourn->date_modification), 'dayhour', 'tzuserrel');
1254 print '</td>';
1255 }
1256
1257 // Extrafields
1258 if (!empty($extralabels)) {
1259 $sql = "SELECT";
1260 $sql .= " fk_object";
1261 foreach ($extralabels as $key => $value) {
1262 $sql .= ", ".$key;
1263 }
1264 $sql .= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price_extrafields";
1265 $sql .= " WHERE fk_object = ".((int) $productfourn->product_fourn_price_id);
1266 $resql = $db->query($sql);
1267 if ($resql) {
1268 if ($db->num_rows($resql) != 1) {
1269 foreach ($extralabels as $key => $value) {
1270 if (!empty($arrayfields['ef.'.$key]['checked']) && !empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1271 print "<td></td>";
1272 }
1273 }
1274 } else {
1275 $obj = $db->fetch_object($resql);
1276 foreach ($extralabels as $key => $value) {
1277 if (!empty($arrayfields['ef.'.$key]['checked']) && !empty($extrafields->attributes["product_fournisseur_price"]['list'][$key]) && $extrafields->attributes["product_fournisseur_price"]['list'][$key] != 3) {
1278 print '<td align="right">'.$extrafields->showOutputField($key, $obj->{$key}, '', 'product_fournisseur_price')."</td>";
1279 }
1280 }
1281 }
1282 $db->free($resql);
1283 }
1284 }
1285
1286 if (is_object($hookmanager)) {
1287 $parameters = array('id_pfp'=>$productfourn->product_fourn_price_id, 'id_fourn'=>(!empty($id_fourn) ? $id_fourn : ''), 'prod_id'=>$object->id);
1288 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action);
1289 }
1290
1291 // Modify-Remove
1292 print '<td class="center nowraponall">';
1293
1294 if ($usercancreate) {
1295 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>";
1296 print ' &nbsp; ';
1297 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>';
1298 }
1299
1300 print '</td>';
1301
1302 print '</tr>';
1303 }
1304
1305 if (empty($product_fourn_list)) {
1306 print '<tr><td colspan="'.$nbfields.'"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
1307 }
1308 } else {
1309 dol_print_error($db);
1310 }
1311
1312 print '</table>';
1313 print '</div>';
1314 print '</form>';
1315 }
1316 }
1317 }
1318} else {
1319 print $langs->trans("ErrorUnknown");
1320}
1321
1322// End of page
1323llxFooter();
1324$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: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 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 a 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...
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.