dolibarr 21.0.0-alpha
price.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
5 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
7 * Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
8 * Copyright (C) 2014-2018 Juanjo Menent <jmenent@2byte.es>
9 * Copyright (C) 2014-2019 Philippe Grand <philippe.grand@atoo-net.com>
10 * Copyright (C) 2014 Ion agorria <ion@agorria.com>
11 * Copyright (C) 2015-2023 Alexandre Spangaro <aspangaro@open-dsi.fr>
12 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
13 * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
14 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
15 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
16 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 3 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <https://www.gnu.org/licenses/>.
30 */
31
38// Load Dolibarr environment
39require '../main.inc.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php';
42require_once DOL_DOCUMENT_ROOT.'/product/class/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';
45
46if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
47 require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php';
48
49 $prodcustprice = new ProductCustomerPrice($db);
50}
51
52// Load translation files required by the page
53$langs->loadLangs(array('products', 'bills', 'companies', 'other'));
54
55$error = 0;
56$errors = array();
57
58$id = GETPOSTINT('id');
59$ref = GETPOST('ref', 'alpha');
60$action = GETPOST('action', 'aZ09');
61$cancel = GETPOST('cancel', 'alpha');
62$eid = GETPOSTINT('eid');
63
64$search_soc = GETPOST('search_soc');
65
66// Security check
67$fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : ''));
68$fieldtype = (!empty($ref) ? 'ref' : 'rowid');
69if ($user->socid) {
70 $socid = $user->socid;
71}
72
73$object = new Product($db);
74if ($id > 0 || !empty($ref)) {
75 $object->fetch($id, $ref);
76}
77
78// Clean param
79if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT')) {
80 $conf->global->PRODUIT_MULTIPRICES_LIMIT = 5;
81}
82
83// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
84$hookmanager->initHooks(array('productpricecard', 'globalcard'));
85
86if ($object->id > 0) {
87 if ($object->type == $object::TYPE_PRODUCT) {
88 restrictedArea($user, 'produit', $object->id, 'product&product', '', '');
89 }
90 if ($object->type == $object::TYPE_SERVICE) {
91 restrictedArea($user, 'service', $object->id, 'product&product', '', '');
92 }
93} else {
94 restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype);
95}
96
97
98/*
99 * Actions
100 */
101
102if ($cancel) {
103 $action = '';
104}
105
106$parameters = array('id' => $id, 'ref' => $ref);
107$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
108if ($reshook < 0) {
109 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
110}
111
112if (empty($reshook)) {
113 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
114 $search_soc = '';
115 }
116
117 if ($action == 'setlabelsellingprice' && $user->admin) {
118 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
119 $keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.GETPOST('pricelevel');
120 dolibarr_set_const($db, $keyforlabel, GETPOST('labelsellingprice', 'alpha'), 'chaine', 0, '', $conf->entity);
121 $action = '';
122 }
123
124 if (($action == 'update_vat') && !$cancel && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
125 $tva_tx_txt = GETPOST('tva_tx', 'alpha'); // tva_tx can be '8.5' or '8.5*' or '8.5 (XXX)' or '8.5* (XXX)'
126
127 $price_label = GETPOST('price_label', 'alpha');
128
129 // We must define tva_tx, npr and local taxes
130 $tva_tx = $tva_tx_txt;
131 $reg = array();
132 $vatratecode = '';
133 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
134 $vatratecode = $reg[1];
135 $tva_tx = preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx_txt); // Remove code into vatrate.
136 }
137
138 $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot
139 $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0;
140 $localtax1 = 0;
141 $localtax2 = 0;
142 $localtax1_type = '0';
143 $localtax2_type = '0';
144 // If value contains the unique code of vat line (new recommended method), we use it to find npr and local taxes
145
146 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
147 // We look into database using code (we can't use get_localtax() because it depends on buyer that is not known). Same in create product.
148 $vatratecode = $reg[1];
149 // Get record from code
150 $sql = "SELECT t.rowid, t.type_vat, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
151 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
152 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
153 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
154 $sql .= " AND t.code = '".$db->escape($vatratecode)."'";
155 $sql .= " AND t.type_vat IN (0, 1)"; // Use only VAT rates type all or i.e. the sales type VAT rates.
156 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
157 $resql = $db->query($sql);
158 if ($resql) {
159 $obj = $db->fetch_object($resql);
160 if ($obj) {
161 $npr = $obj->recuperableonly;
162 $localtax1 = $obj->localtax1;
163 $localtax2 = $obj->localtax2;
164 $localtax1_type = $obj->localtax1_type;
165 $localtax2_type = $obj->localtax2_type;
166 }
167 }
168 } else {
169 // Get record with empty code
170 $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
171 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
172 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
173 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
174 $sql .= " AND t.code = ''";
175 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
176 $resql = $db->query($sql);
177 if ($resql) {
178 $obj = $db->fetch_object($resql);
179 if ($obj) {
180 $npr = $obj->recuperableonly;
181 $localtax1 = $obj->localtax1;
182 $localtax2 = $obj->localtax2;
183 $localtax1_type = $obj->localtax1_type;
184 $localtax2_type = $obj->localtax2_type;
185 }
186 }
187 }
188
189 $object->default_vat_code = $vatratecode;
190 $object->tva_tx = $tva_tx;
191 $object->tva_npr = $npr;
192 $object->localtax1_tx = $localtax1;
193 $object->localtax2_tx = $localtax2;
194 $object->localtax1_type = $localtax1_type;
195 $object->localtax2_type = $localtax2_type;
196 $object->price_label = $price_label;
197
198 $db->begin();
199
200 $resql = $object->update($object->id, $user);
201 if ($resql <= 0) {
202 $error++;
203 setEventMessages($object->error, $object->errors, 'errors');
204 }
205
206 if (!$error) {
207 if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
208 $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT');
209 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
210 // Force the update of the price of the product using the new VAT
211 if ($object->multiprices_base_type[$i] == 'HT') {
212 $oldprice = $object->multiprices[$i];
213 $oldminprice = $object->multiprices_min[$i];
214 } else {
215 $oldprice = $object->multiprices_ttc[$i];
216 $oldminprice = $object->multiprices_min_ttc[$i];
217 }
218 $oldpricebasetype = $object->multiprices_base_type[$i];
219 $oldnpr = $object->multiprices_recuperableonly[$i];
220
221 //$localtaxarray=array('0'=>$localtax1_type,'1'=>$localtax1,'2'=>$localtax2_type,'3'=>$localtax2);
222 $localtaxarray = array(); // We do not store localtaxes into product, we will use instead the "vat code" to retrieve them.
223 $level = $i;
224 $ret = $object->updatePrice($oldprice, $oldpricebasetype, $user, $tva_tx, $oldminprice, $level, $oldnpr, 0, 0, $localtaxarray, $vatratecode, $price_label);
225
226 if ($ret < 0) {
227 $error++;
228 setEventMessages($object->error, $object->errors, 'errors');
229 }
230 }
231 } else {
232 // Force the update of the price of the product using the new VAT
233 if ($object->price_base_type == 'HT') {
234 $oldprice = $object->price;
235 $oldminprice = $object->price_min;
236 } else {
237 $oldprice = $object->price_ttc;
238 $oldminprice = $object->price_min_ttc;
239 }
240 $oldpricebasetype = $object->price_base_type;
241 $oldnpr = $object->tva_npr;
242
243 //$localtaxarray=array('0'=>$localtax1_type,'1'=>$localtax1,'2'=>$localtax2_type,'3'=>$localtax2);
244 $localtaxarray = array(); // We do not store localtaxes into product, we will use instead the "vat code" to retrieve them when required.
245 $level = 0;
246 $ret = $object->updatePrice($oldprice, $oldpricebasetype, $user, $tva_tx, $oldminprice, $level, $oldnpr, 0, 0, $localtaxarray, $vatratecode, $price_label);
247
248 if ($ret < 0) {
249 $error++;
250 setEventMessages($object->error, $object->errors, 'errors');
251 }
252 }
253 }
254
255 if (!$error) {
256 $db->commit();
257 } else {
258 $db->rollback();
259 }
260
261 $action = '';
262 }
263
264 if (($action == 'update_price' || $action == 'update_level_price') && !$cancel && $object->getRights()->creer) {
265 $error = 0;
266 $pricestoupdate = array();
267
268 $psq = GETPOST('psqflag');
269 $psq = empty($newpsq) ? 0 : $newpsq;
270 $maxpricesupplier = $object->min_recommended_price();
271
272 if (isModEnabled('dynamicprices')) {
273 $object->fk_price_expression = empty($eid) ? 0 : $eid; //0 discards expression
274
275 if ($object->fk_price_expression != 0) {
276 //Check the expression validity by parsing it
277 require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php';
278 $priceparser = new PriceParser($db);
279
280 if ($priceparser->parseProduct($object) < 0) {
281 $error++;
282 setEventMessages($priceparser->translatedError(), null, 'errors');
283 }
284 }
285 }
286
287 // Multiprices
288 if (!$error && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || ($action == 'update_level_price' && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')))) {
289 $newprice = GETPOST('price', 'array');
290 $newprice_min = GETPOST('price_min', 'array');
291 $newpricebase = GETPOST('multiprices_base_type', 'array');
292 $newvattx = GETPOST('tva_tx', 'array');
293 $newvatnpr = GETPOST('tva_npr', 'array');
294 $newlocaltax1_tx = GETPOST('localtax1_tx', 'array');
295 $newlocaltax1_type = GETPOST('localtax1_type', 'array');
296 $newlocaltax2_tx = GETPOST('localtax2_tx', 'array');
297 $newlocaltax2_type = GETPOST('localtax2_type', 'array');
298
299 //Shall we generate prices using price rules?
300 $object->price_autogen = (int) (GETPOST('usePriceRules') == 'on');
301
302 $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT');
303 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
304 if (!isset($newprice[$i])) {
305 continue;
306 }
307
308 $tva_tx_txt = $newvattx[$i];
309
310 $tva_tx = $tva_tx_txt;
311 $vatratecode = '';
312 $reg = array();
313 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
314 $vat_src_code = $reg[1];
315 $tva_tx = preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx_txt); // Remove code into vatrate.
316 }
317 $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot
318
319 $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0;
320 $localtax1 = $newlocaltax1_tx[$i];
321 $localtax1_type = $newlocaltax1_type[$i];
322 $localtax2 = $newlocaltax2_tx[$i];
323 $localtax2_type = $newlocaltax2_type[$i];
324 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
325 // We look into database using code
326 $vatratecode = $reg[1];
327 // Get record from code
328 $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
329 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
330 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
331 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
332 $sql .= " AND t.code ='".$db->escape($vatratecode)."'";
333 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
334 $resql = $db->query($sql);
335 if ($resql) {
336 $obj = $db->fetch_object($resql);
337 if ($obj) {
338 $npr = $obj->recuperableonly;
339 $localtax1 = $obj->localtax1;
340 $localtax2 = $obj->localtax2;
341 $localtax1_type = $obj->localtax1_type;
342 $localtax2_type = $obj->localtax2_type;
343 }
344
345 // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule.
346 if (in_array($mysoc->country_code, array('ES'))) {
347 $localtax1 = get_localtax($tva_tx, 1);
348 $localtax2 = get_localtax($tva_tx, 2);
349 }
350 }
351 } else {
352 // Get record with empty code
353 $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
354 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
355 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
356 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
357 $sql .= " AND t.code = ''";
358 $resql = $db->query($sql);
359 if ($resql) {
360 $obj = $db->fetch_object($resql);
361 if ($obj) {
362 $npr = $obj->recuperableonly;
363 $localtax1 = $obj->localtax1;
364 $localtax2 = $obj->localtax2;
365 $localtax1_type = $obj->localtax1_type;
366 $localtax2_type = $obj->localtax2_type;
367 }
368 }
369 }
370
371 $pricestoupdate[$i] = array(
372 'price' => price2num($newprice[$i], '', 2),
373 'price_min' => price2num($newprice_min[$i], '', 2),
374 'price_base_type' => $newpricebase[$i],
375 'default_vat_code' => $vatratecode,
376 'vat_tx' => $tva_tx, // default_vat_code should be used in priority in a future
377 'npr' => $npr, // default_vat_code should be used in priority in a future
378 'localtaxes_array' => array('0' => $localtax1_type, '1' => $localtax1, '2' => $localtax2_type, '3' => $localtax2) // default_vat_code should be used in priority in a future
379 );
380
381 //If autogeneration is enabled, then we only set the first level
382 if ($object->price_autogen) {
383 break;
384 }
385 }
386 } elseif (!$error) {
387 $newprice = price2num(GETPOST('price', 'alpha'), '', 2);
388 $newprice_min = price2num(GETPOST('price_min', 'alpha'), '', 2);
389 $newpricebase = GETPOST('price_base_type', 'alpha');
390 $tva_tx_txt = GETPOST('tva_tx', 'alpha'); // tva_tx can be '8.5' or '8.5*' or '8.5 (XXX)' or '8.5* (XXX)'
391 $price_label = GETPOST('price_label', 'alpha');
392
393 $tva_tx = $tva_tx_txt;
394 $vatratecode = '';
395 $reg = array();
396 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
397 $vat_src_code = $reg[1];
398 $tva_tx = preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx_txt); // Remove code into vatrate.
399 }
400 $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot
401
402 $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0;
403 $localtax1 = 0;
404 $localtax2 = 0;
405 $localtax1_type = '0';
406 $localtax2_type = '0';
407 // If value contains the unique code of vat line (new recommended method), we use it to find npr and local taxes
408 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
409 // We look into database using code
410 $vatratecode = $reg[1];
411 // Get record from code
412 $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
413 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
414 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
415 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
416 $sql .= " AND t.code ='".$db->escape($vatratecode)."'";
417 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
418 $resql = $db->query($sql);
419 if ($resql) {
420 $obj = $db->fetch_object($resql);
421 if ($obj) {
422 $npr = $obj->recuperableonly;
423 $localtax1 = $obj->localtax1;
424 $localtax2 = $obj->localtax2;
425 $localtax1_type = $obj->localtax1_type;
426 $localtax2_type = $obj->localtax2_type;
427 }
428
429 // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule.
430 if (in_array($mysoc->country_code, array('ES'))) {
431 $localtax1 = get_localtax($tva_tx, 1);
432 $localtax2 = get_localtax($tva_tx, 2);
433 }
434 }
435 } else {
436 // Get record with empty code
437 $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
438 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
439 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
440 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
441 $sql .= " AND t.code = ''";
442 $resql = $db->query($sql);
443 if ($resql) {
444 $obj = $db->fetch_object($resql);
445 if ($obj) {
446 $npr = $obj->recuperableonly;
447 $localtax1 = $obj->localtax1;
448 $localtax2 = $obj->localtax2;
449 $localtax1_type = $obj->localtax1_type;
450 $localtax2_type = $obj->localtax2_type;
451 }
452 }
453 }
454
455 $pricestoupdate[0] = array(
456 'price' => $newprice,
457 'price_label' => $price_label,
458 'price_min' => $newprice_min,
459 'price_base_type' => $newpricebase,
460 'default_vat_code' => $vatratecode,
461 'vat_tx' => $tva_tx, // default_vat_code should be used in priority in a future
462 'npr' => $npr, // default_vat_code should be used in priority in a future
463 'localtaxes_array' => array('0' => $localtax1_type, '1' => $localtax1, '2' => $localtax2_type, '3' => $localtax2) // default_vat_code should be used in priority in a future
464 );
465 }
466
467 if (!$error) {
468 $db->begin();
469
470 foreach ($pricestoupdate as $key => $val) {
471 $newprice = $val['price'];
472
473 if ($val['price'] < $val['price_min'] && !empty($object->fk_price_expression)) {
474 $newprice = $val['price_min']; //Set price same as min, the user will not see the
475 }
476
477 $newprice = price2num($newprice, 'MU');
478 $newprice_min = price2num($val['price_min'], 'MU');
479 $newvattx = price2num($val['vat_tx']);
480
481 if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE') && $newprice_min < $maxpricesupplier) {
482 setEventMessages($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, - 1, - 1, 'auto')), null, 'errors');
483 $error++;
484 break;
485 }
486
487 // If price has changed, we update it
488 if (!array_key_exists($key, $object->multiprices) || $object->multiprices[$key] != $newprice || $object->multiprices_min[$key] != $newprice_min || $object->multiprices_base_type[$key] != $val['price_base_type'] || $object->multiprices_tva_tx[$key] != $newvattx) {
489 $res = $object->updatePrice($newprice, $val['price_base_type'], $user, $val['vat_tx'], $newprice_min, $key, $val['npr'], $psq, 0, $val['localtaxes_array'], $val['default_vat_code'], $val['price_label']);
490 } else {
491 $res = 0;
492 }
493
494 if ($res < 0) {
495 $error++;
496 setEventMessages($object->error, $object->errors, 'errors');
497 break;
498 }
499 }
500 }
501
502 if (!$error && $object->update($object->id, $user) < 0) {
503 $error++;
504 setEventMessages($object->error, $object->errors, 'errors');
505 }
506
507 if (empty($error)) {
508 $action = '';
509 setEventMessages($langs->trans("RecordSaved"), null, 'mesgs');
510 $db->commit();
511 } else {
512 $action = 'edit_price';
513 $db->rollback();
514 }
515 }
516
517
518 if ($action == 'delete' && $user->hasRight('produit', 'supprimer')) {
519 $result = $object->log_price_delete($user, GETPOSTINT('lineid'));
520 if ($result < 0) {
521 setEventMessages($object->error, $object->errors, 'errors');
522 }
523 }
524
525 // Set Price by quantity
526 if ($action == 'activate_price_by_qty') {
527 // Activating product price by quantity add a new price line with price_by_qty set to 1
528 $level = GETPOSTINT('level');
529 $basePrice = ($object->price_base_type == 'HT') ? $object->price : $object->price_ttc;
530 $basePriceMin = ($object->price_base_type == 'HT') ? $object->price_min : $object->price_min_ttc;
531 $ret = $object->updatePrice($basePrice, $object->price_base_type, $user, $object->tva_tx, $basePriceMin, $level, $object->tva_npr, 1);
532
533 if ($ret < 0) {
534 setEventMessages($object->error, $object->errors, 'errors');
535 }
536 }
537 // Unset Price by quantity
538 if ($action == 'disable_price_by_qty') {
539 // Disabling product price by quantity add a new price line with price_by_qty set to 0
540 $level = GETPOSTINT('level');
541 $basePrice = ($object->price_base_type == 'HT') ? $object->price : $object->price_ttc;
542 $basePriceMin = ($object->price_base_type == 'HT') ? $object->price_min : $object->price_min_ttc;
543 $ret = $object->updatePrice($basePrice, $object->price_base_type, $user, $object->tva_tx, $basePriceMin, $level, $object->tva_npr, 0);
544
545 if ($ret < 0) {
546 setEventMessages($object->error, $object->errors, 'errors');
547 }
548 }
549
550 if ($action == 'edit_price_by_qty') { // Edition d'un prix par quantité
551 $rowid = GETPOSTINT('rowid');
552 }
553
554 // Add or update price by quantity
555 if ($action == 'update_price_by_qty') {
556 // Récupération des variables
557 $rowid = GETPOSTINT('rowid');
558 $priceid = GETPOSTINT('priceid');
559 $newprice = price2num(GETPOST("price"), 'MU', 2);
560 // $newminprice=price2num(GETPOST("price_min"),'MU'); // TODO : Add min price management
561 $quantity = price2num(GETPOST('quantity'), 'MS', 2);
562 $remise_percent = price2num(GETPOST('remise_percent'), '', 2);
563 $remise = 0; // TODO : allow discount by amount when available on documents
564
565 if (empty($quantity)) {
566 $error++;
567 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Qty")), null, 'errors');
568 }
569 if (empty($newprice)) {
570 $error++;
571 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Price")), null, 'errors');
572 }
573 if (!$error) {
574 // Calcul du prix HT et du prix unitaire
575 if ($object->price_base_type == 'TTC') {
576 $price = (float) price2num($newprice) / (1 + ($object->tva_tx / 100));
577 }
578
579 $price = price2num($newprice, 'MU');
580 $unitPrice = price2num((float) $price / (float) $quantity, 'MU');
581
582 // Ajout / mise à jour
583 if ($rowid > 0) {
584 $sql = "UPDATE ".MAIN_DB_PREFIX."product_price_by_qty SET";
585 $sql .= " price=".((float) $price).",";
586 $sql .= " unitprice=".((float) $unitPrice).",";
587 $sql .= " quantity=".((float) $quantity).",";
588 $sql .= " remise_percent=".((float) $remise_percent).",";
589 $sql .= " remise=".((float) $remise);
590 $sql .= " WHERE rowid = ".((int) $rowid);
591
592 $result = $db->query($sql);
593 if (!$result) {
594 dol_print_error($db);
595 }
596 } else {
597 $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price_by_qty (fk_product_price,price,unitprice,quantity,remise_percent,remise) values (";
598 $sql .= ((int) $priceid).','.((float) $price).','.((float) $unitPrice).','.((float) $quantity).','.((float) $remise_percent).','.((float) $remise).')';
599
600 $result = $db->query($sql);
601 if (!$result) {
602 if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
603 setEventMessages($langs->trans("DuplicateRecord"), null, 'errors');
604 } else {
605 dol_print_error($db);
606 }
607 }
608 }
609 }
610 }
611
612 if ($action == 'delete_price_by_qty') {
613 $rowid = GETPOSTINT('rowid');
614 if (!empty($rowid)) {
615 $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price_by_qty";
616 $sql .= " WHERE rowid = ".((int) $rowid);
617
618 $result = $db->query($sql);
619 } else {
620 setEventMessages(('delete_price_by_qty'.$langs->transnoentities('MissingIds')), null, 'errors');
621 }
622 }
623
624 if ($action == 'delete_all_price_by_qty') {
625 $priceid = GETPOSTINT('priceid');
626 if (!empty($rowid)) {
627 $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price_by_qty";
628 $sql .= " WHERE fk_product_price = ".((int) $priceid);
629
630 $result = $db->query($sql);
631 } else {
632 setEventMessages(('delete_price_by_qty'.$langs->transnoentities('MissingIds')), null, 'errors');
633 }
634 }
635
641 if ($action == 'add_customer_price_confirm' && !$cancel && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
642 $maxpricesupplier = $object->min_recommended_price();
643
644 $update_child_soc = GETPOSTINT('updatechildprice');
645
646 // add price by customer
647 $prodcustprice->fk_soc = GETPOSTINT('socid');
648 $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha');
649 $prodcustprice->fk_product = $object->id;
650 $prodcustprice->price = price2num(GETPOST("price"), 'MU');
651 $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU');
652 $prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha');
653 $prodcustprice->price_label = GETPOST("price_label", 'alpha');
654
655 $tva_tx_txt = GETPOST("tva_tx", 'alpha');
656
657 $tva_tx = $tva_tx_txt;
658 $vatratecode = '';
659 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
660 $vat_src_code = $reg[1];
661 $tva_tx = preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx_txt); // Remove code into vatrate.
662 }
663 $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot
664
665 $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0;
666 $localtax1 = 0;
667 $localtax2 = 0;
668 $localtax1_type = '0';
669 $localtax2_type = '0';
670 // If value contains the unique code of vat line (new recommended method), we use it to find npr and local taxes
671 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
672 // We look into database using code
673 $vatratecode = $reg[1];
674 // Get record from code
675 $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
676 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
677 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
678 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
679 $sql .= " AND t.code ='".$db->escape($vatratecode)."'";
680 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
681 $resql = $db->query($sql);
682 if ($resql) {
683 $obj = $db->fetch_object($resql);
684 if ($obj) {
685 $npr = $obj->recuperableonly;
686 $localtax1 = $obj->localtax1;
687 $localtax2 = $obj->localtax2;
688 $localtax1_type = $obj->localtax1_type;
689 $localtax2_type = $obj->localtax2_type;
690 }
691
692 // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule.
693 if (in_array($mysoc->country_code, array('ES'))) {
694 $localtax1 = get_localtax($tva_tx, 1);
695 $localtax2 = get_localtax($tva_tx, 2);
696 }
697 }
698 } else {
699 // Get record with empty code
700 $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
701 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
702 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
703 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
704 $sql .= " AND t.code = ''";
705 $resql = $db->query($sql);
706 if ($resql) {
707 $obj = $db->fetch_object($resql);
708 if ($obj) {
709 $npr = $obj->recuperableonly;
710 $localtax1 = $obj->localtax1;
711 $localtax2 = $obj->localtax2;
712 $localtax1_type = $obj->localtax1_type;
713 $localtax2_type = $obj->localtax2_type;
714 }
715 }
716 }
717
718 $prodcustprice->default_vat_code = $vatratecode;
719 $prodcustprice->tva_tx = $tva_tx;
720 $prodcustprice->recuperableonly = $npr;
721 $prodcustprice->localtax1_tx = $localtax1;
722 $prodcustprice->localtax2_tx = $localtax2;
723 $prodcustprice->localtax1_type = $localtax1_type;
724 $prodcustprice->localtax2_type = $localtax2_type;
725
726 if (!($prodcustprice->fk_soc > 0)) {
727 $langs->load("errors");
728 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ThirdParty")), null, 'errors');
729 $error++;
730 $action = 'add_customer_price';
731 }
732 if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE') && $prodcustprice->price_min < $maxpricesupplier) {
733 $langs->load("errors");
734 setEventMessages($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')), null, 'errors');
735 $error++;
736 $action = 'add_customer_price';
737 }
738
739 if (!$error) {
740 $result = $prodcustprice->create($user, 0, $update_child_soc);
741
742 if ($result < 0) {
743 setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
744 } else {
745 setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
746 }
747
748 $action = '';
749 }
750 }
751
752 if ($action == 'delete_customer_price' && ($user->hasRight('produit', 'supprimer') || $user->hasRight('service', 'supprimer'))) {
753 // Delete price by customer
754 $prodcustprice->id = GETPOSTINT('lineid');
755 $result = $prodcustprice->delete($user);
756
757 if ($result < 0) {
758 setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
759 } else {
760 setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
761 }
762 $action = '';
763 }
764
765 if ($action == 'update_customer_price_confirm' && !$cancel && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
766 $maxpricesupplier = $object->min_recommended_price();
767
768 $update_child_soc = GETPOSTINT('updatechildprice');
769
770 $prodcustprice->fetch(GETPOSTINT('lineid'));
771
772 // update price by customer
773 $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha');
774 $prodcustprice->price = price2num(GETPOST("price"), 'MU');
775 $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU');
776 $prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha');
777 $prodcustprice->price_label = GETPOST("price_label", 'alpha');
778
779 $tva_tx_txt = GETPOST("tva_tx");
780
781 $tva_tx = $tva_tx_txt;
782 $vatratecode = '';
783 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
784 $vat_src_code = $reg[1];
785 $tva_tx = preg_replace('/\s*\‍(.*\‍)/', '', $tva_tx_txt); // Remove code into vatrate.
786 }
787 $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot
788
789 $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0;
790 $localtax1 = 0;
791 $localtax2 = 0;
792 $localtax1_type = '0';
793 $localtax2_type = '0';
794 // If value contains the unique code of vat line (new recommended method), we use it to find npr and local taxes
795 if (preg_match('/\‍((.*)\‍)/', $tva_tx_txt, $reg)) {
796 // We look into database using code
797 $vatratecode = $reg[1];
798 // Get record from code
799 $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
800 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
801 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
802 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
803 $sql .= " AND t.code ='".$db->escape($vatratecode)."'";
804 $sql .= " AND t.entity IN (".getEntity('c_tva').")";
805 $resql = $db->query($sql);
806 if ($resql) {
807 $obj = $db->fetch_object($resql);
808 if ($obj) {
809 $npr = $obj->recuperableonly;
810 $localtax1 = $obj->localtax1;
811 $localtax2 = $obj->localtax2;
812 $localtax1_type = $obj->localtax1_type;
813 $localtax2_type = $obj->localtax2_type;
814 }
815
816 // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule.
817 if (in_array($mysoc->country_code, array('ES'))) {
818 $localtax1 = get_localtax($tva_tx, 1);
819 $localtax2 = get_localtax($tva_tx, 2);
820 }
821 }
822 } else {
823 // Get record with empty code
824 $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
825 $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
826 $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
827 $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
828 $sql .= " AND t.code = ''";
829 $resql = $db->query($sql);
830 if ($resql) {
831 $obj = $db->fetch_object($resql);
832 if ($obj) {
833 $npr = $obj->recuperableonly;
834 $localtax1 = $obj->localtax1;
835 $localtax2 = $obj->localtax2;
836 $localtax1_type = $obj->localtax1_type;
837 $localtax2_type = $obj->localtax2_type;
838 }
839 }
840 }
841
842 $prodcustprice->default_vat_code = $vatratecode;
843 $prodcustprice->tva_tx = $tva_tx;
844 $prodcustprice->recuperableonly = $npr;
845 $prodcustprice->localtax1_tx = $localtax1;
846 $prodcustprice->localtax2_tx = $localtax2;
847 $prodcustprice->localtax1_type = $localtax1_type;
848 $prodcustprice->localtax2_type = $localtax2_type;
849
850 if ($prodcustprice->price_min < $maxpricesupplier && getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) {
851 setEventMessages($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')), null, 'errors');
852 $error++;
853 $action = 'update_customer_price';
854 }
855
856 if (!$error) {
857 $result = $prodcustprice->update($user, 0, $update_child_soc);
858
859 if ($result < 0) {
860 setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
861 } else {
862 setEventMessages($langs->trans("Save"), null, 'mesgs');
863 }
864
865 $action = '';
866 }
867 }
868}
869
870
871/*
872 * View
873 */
874
875$form = new Form($db);
876
877if (!empty($id) || !empty($ref)) {
878 // fetch updated prices
879 $object->fetch($id, $ref);
880}
881
882$title = $langs->trans('ProductServiceCard');
883$helpurl = '';
884$shortlabel = dol_trunc($object->label, 16);
885if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) {
886 $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('SellingPrices');
887 $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
888}
889if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) {
890 $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('SellingPrices');
891 $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
892}
893
894llxHeader('', $title, $helpurl, '', 0, 0, '', '', '', 'classforhorizontalscrolloftabs mod-product page-price');
895
896$head = product_prepare_head($object);
897$titre = $langs->trans("CardProduct".$object->type);
898$picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
899
900print dol_get_fiche_head($head, 'price', $titre, -1, $picto);
901
902$linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1&type='.$object->type.'">'.$langs->trans("BackToList").'</a>';
903$object->next_prev_filter = "fk_product_type = ".((int) $object->type);
904
905$shownav = 1;
906if ($user->socid && !in_array('product', explode(',', getDolGlobalString('MAIN_MODULES_FOR_EXTERNAL')))) {
907 $shownav = 0;
908}
909
910dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
911
912
913print '<div class="fichecenter">';
914
915print '<div class="underbanner clearboth"></div>';
916print '<table class="border tableforfield centpercent">';
917
918// Price per customer segment/level
919if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
920 // Price and min price are variable (depends on level of company).
921 if (!empty($socid)) {
922 $soc = new Societe($db);
923 $soc->id = $socid;
924 $soc->fetch($socid);
925
926 // Type
927 if (isModEnabled("product") && isModEnabled("service")) {
928 $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service");
929 print '<tr><td class="">';
930 print (!getDolGlobalString('PRODUCT_DENY_CHANGE_PRODUCT_TYPE')) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type');
931 print '</td><td>';
932 print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat);
933 print '</td></tr>';
934 }
935
936 // Selling price
937 print '<tr><td class="titlefieldcreate">';
938 print $langs->trans("SellingPrice");
939 print '</td>';
940 print '<td colspan="2">';
941 if ($object->multiprices_base_type[$soc->price_level] == 'TTC') {
942 print '<span class="amount">'.price($object->multiprices_ttc[$soc->price_level]).'</span>';
943 } else {
944 print '<span class="amount">'.price($object->multiprices[$soc->price_level]).'</span>';
945 }
946 if ($object->multiprices_base_type[$soc->price_level]) {
947 print ' '.$langs->trans($object->multiprices_base_type[$soc->price_level]);
948 } else {
949 print ' '.$langs->trans($object->price_base_type);
950 }
951 print '</td></tr>';
952
953 // Price min
954 print '<tr><td>'.$langs->trans("MinPrice").'</td><td colspan="2">';
955 if ($object->multiprices_base_type[$soc->price_level] == 'TTC') {
956 print price($object->multiprices_min_ttc[$soc->price_level]).' '.$langs->trans($object->multiprices_base_type[$soc->price_level]);
957 } else {
958 print price($object->multiprices_min[$soc->price_level]).' '.$langs->trans(empty($object->multiprices_base_type[$soc->price_level]) ? 'HT' : $object->multiprices_base_type[$soc->price_level]);
959 }
960 print '</td></tr>';
961
962 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
963 // TVA
964 print '<tr><td>'.$langs->trans("DefaultTaxRate").'</td><td colspan="2">';
965
966 $positiverates = '';
967 if (price2num($object->multiprices_tva_tx[$soc->price_level])) {
968 $positiverates .= ($positiverates ? '/' : '').price2num($object->multiprices_tva_tx[$soc->price_level]);
969 }
970 if (price2num($object->multiprices_localtax1_type[$soc->price_level])) {
971 $positiverates .= ($positiverates ? '/' : '').price2num($object->multiprices_localtax1_tx[$soc->price_level]);
972 }
973 if (price2num($object->multiprices_localtax2_type[$soc->price_level])) {
974 $positiverates .= ($positiverates ? '/' : '').price2num($object->multiprices_localtax2_tx[$soc->price_level]);
975 }
976 if (empty($positiverates)) {
977 $positiverates = '0';
978 }
979 echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr);
980 //print vatrate($object->multiprices_tva_tx[$soc->price_level], true);
981 print '</td></tr>';
982 } else {
983 // TVA
984 print '<tr><td>'.$langs->trans("DefaultTaxRate").'</td><td>';
985
986 $positiverates = '';
987 if (price2num($object->tva_tx)) {
988 $positiverates .= ($positiverates ? '/' : '').price2num($object->tva_tx);
989 }
990 if (price2num($object->localtax1_type)) {
991 $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax1_tx);
992 }
993 if (price2num($object->localtax2_type)) {
994 $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax2_tx);
995 }
996 if (empty($positiverates)) {
997 $positiverates = '0';
998 }
999 echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr);
1000 /*
1001 if ($object->default_vat_code)
1002 {
1003 print vatrate($object->tva_tx, true) . ' ('.$object->default_vat_code.')';
1004 }
1005 else print vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true);*/
1006 print '</td></tr>';
1007 }
1008 } else {
1009 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility
1010 // Type
1011 if (isModEnabled("product") && isModEnabled("service")) {
1012 $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service");
1013 print '<tr><td class="">';
1014 print (!getDolGlobalString('PRODUCT_DENY_CHANGE_PRODUCT_TYPE')) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type');
1015 print '</td><td>';
1016 print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat);
1017 print '</td></tr>';
1018 }
1019
1020 // We show only vat for level 1
1021 print '<tr><td class="titlefieldcreate">'.$langs->trans("DefaultTaxRate").'</td>';
1022 print '<td colspan="2">'.vatrate($object->multiprices_tva_tx[1], true).'</td>';
1023 print '</tr>';
1024 } else {
1025 // Type
1026 if (isModEnabled("product") && isModEnabled("service")) {
1027 $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service");
1028 print '<tr><td class="">';
1029 print (!getDolGlobalString('PRODUCT_DENY_CHANGE_PRODUCT_TYPE')) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type');
1030 print '</td><td>';
1031 print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat);
1032 print '</td></tr>';
1033 }
1034
1035 // TVA
1036 print '<!-- Default VAT Rate -->';
1037 print '<tr><td class="titlefieldcreate">'.$langs->trans("DefaultTaxRate").'</td><td>';
1038
1039 // TODO We show localtax from $object, but this properties may not be correct. Only value $object->default_vat_code is guaranteed.
1040 $positiverates = '';
1041 if (price2num($object->tva_tx)) {
1042 $positiverates .= ($positiverates ? '<span class="opacitymedium">/</span>' : '').price2num($object->tva_tx);
1043 }
1044 if (price2num($object->localtax1_type)) {
1045 $positiverates .= ($positiverates ? '<span class="opacitymedium">/</span>' : '').price2num($object->localtax1_tx);
1046 }
1047 if (price2num($object->localtax2_type)) {
1048 $positiverates .= ($positiverates ? '<span class="opacitymedium">/</span>' : '').price2num($object->localtax2_tx);
1049 }
1050 if (empty($positiverates)) {
1051 $positiverates = '0';
1052 }
1053
1054 print vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr, 1);
1055 /*
1056 if ($object->default_vat_code)
1057 {
1058 print vatrate($object->tva_tx, true) . ' ('.$object->default_vat_code.')';
1059 }
1060 else print vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true);*/
1061 print '</td></tr>';
1062 }
1063 print '</table>';
1064
1065 print '<br>';
1066
1067 print '<table class="noborder tableforfield centpercent">';
1068 print '<tr class="liste_titre"><td>';
1069 print $langs->trans("PriceLevel");
1070 if ($user->admin) {
1071 print ' <a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editlabelsellingprice&token='.newToken().'&pricelevel='.$i.'&id='.$object->id.'">'.img_edit($langs->trans('EditSellingPriceLabel'), 0).'</a>';
1072 }
1073 print '</td>';
1074 print '<td style="text-align: right">'.$langs->trans("SellingPrice").'</td>';
1075 print '<td style="text-align: right">'.$langs->trans("MinPrice").'</td>';
1076 print '</tr>';
1077
1078 $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT');
1079 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
1080 print '<tr class="oddeven">';
1081
1082 // Label of price
1083 print '<td>';
1084 $keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.$i;
1085 if (preg_match('/editlabelsellingprice/', $action)) {
1086 print '<form method="post" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">';
1087 print '<input type="hidden" name="token" value="'.newToken().'">';
1088 print '<input type="hidden" name="action" value="setlabelsellingprice">';
1089 print '<input type="hidden" name="pricelevel" value="'.$i.'">';
1090 print $langs->trans("SellingPrice").' '.$i.' - ';
1091 print '<input class="maxwidthonsmartphone" type="text" name="labelsellingprice" value="' . getDolGlobalString($keyforlabel).'">';
1092 print '&nbsp;<input type="submit" class="button smallpaddingimp" value="'.$langs->trans("Modify").'">';
1093 print '</form>';
1094 } else {
1095 print $langs->trans("SellingPrice").' '.$i;
1096 if (getDolGlobalString($keyforlabel)) {
1097 print ' - '.$langs->trans(getDolGlobalString($keyforlabel));
1098 }
1099 }
1100 print '</td>';
1101
1102 if ($object->multiprices_base_type [$i] == 'TTC') {
1103 print '<td class="right"><span class="amount">'.price($object->multiprices_ttc[$i]);
1104 } else {
1105 print '<td class="right"><span class="amount">'.price($object->multiprices[$i]);
1106 }
1107
1108 if ($object->multiprices_base_type[$i]) {
1109 print ' '.$langs->trans($object->multiprices_base_type [$i]).'</span></td>';
1110 } else {
1111 print ' '.$langs->trans($object->price_base_type).'</span></td>';
1112 }
1113
1114 // Prix min
1115 print '<td style="text-align: right">';
1116 if (empty($object->multiprices_base_type[$i])) {
1117 $object->multiprices_base_type[$i] = "HT";
1118 }
1119 if ($object->multiprices_base_type[$i] == 'TTC') {
1120 print price($object->multiprices_min_ttc[$i]).' '.$langs->trans($object->multiprices_base_type[$i]);
1121 } else {
1122 print price($object->multiprices_min[$i]).' '.$langs->trans($object->multiprices_base_type[$i]);
1123 }
1124 print '</td></tr>';
1125
1126 // Price by quantity
1127 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { // TODO Fix the form included into a tr instead of a td
1128 print '<tr><td>'.$langs->trans("PriceByQuantity").' '.$i;
1129 if (getDolGlobalString($keyforlabel)) {
1130 print ' - '.$langs->trans(getDolGlobalString($keyforlabel));
1131 }
1132 print '</td><td colspan="2">';
1133
1134 if ($object->prices_by_qty[$i] == 1) {
1135 print '<table width="50%" class="border" summary="List of quantities">';
1136
1137 print '<tr class="liste_titre">';
1138 print '<td>'.$langs->trans("PriceByQuantityRange").' '.$i.'</td>';
1139 print '<td class="right">'.$langs->trans("HT").'</td>';
1140 print '<td class="right">'.$langs->trans("UnitPrice").'</td>';
1141 print '<td class="right">'.$langs->trans("Discount").'</td>';
1142 print '<td>&nbsp;</td>';
1143 print '</tr>';
1144 foreach ($object->prices_by_qty_list[$i] as $ii => $prices) {
1145 if ($action == 'edit_price_by_qty' && $rowid == $prices['rowid'] && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
1146 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
1147 print '<input type="hidden" name="token" value="'.newToken().'">';
1148 print '<input type="hidden" name="action" value="update_price_by_qty">';
1149 print '<input type="hidden" name="priceid" value="'.$object->prices_by_qty_id[$i].'">';
1150 print '<input type="hidden" value="'.$prices['rowid'].'" name="rowid">';
1151 print '<tr class="'.($ii % 2 == 0 ? 'pair' : 'impair').'">';
1152 print '<td><input size="5" type="text" value="'.$prices['quantity'].'" name="quantity"></td>';
1153 print '<td class="right" colspan="2"><input size="10" type="text" value="'.price2num($prices['price'], 'MU').'" name="price">&nbsp;'.$object->price_base_type.'</td>';
1154 print '<td class="right nowraponall"><input size="5" type="text" value="'.$prices['remise_percent'].'" name="remise_percent"> %</td>';
1155 print '<td class="center"><input type="submit" value="'.$langs->trans("Modify").'" class="button"></td>';
1156 print '</tr>';
1157 print '</form>';
1158 } else {
1159 print '<tr class="'.($ii % 2 == 0 ? 'pair' : 'impair').'">';
1160 print '<td>'.$prices['quantity'].'</td>';
1161 print '<td class="right">'.price($prices['price']).'</td>';
1162 print '<td class="right">'.price($prices['unitprice']).'</td>';
1163 print '<td class="right">'.price($prices['remise_percent']).' %</td>';
1164 print '<td class="center">';
1165 if (($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
1166 print '<a class="editfielda marginleftonly marginrightonly" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit_price_by_qty&token='.newToken().'&rowid='.$prices["rowid"].'">';
1167 print img_edit().'</a>';
1168 print '<a class="marginleftonly marginrightonly" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete_price_by_qty&token='.newToken().'&rowid='.$prices["rowid"].'">';
1169 print img_delete().'</a>';
1170 } else {
1171 print '&nbsp;';
1172 }
1173 print '</td>';
1174 print '</tr>';
1175 }
1176 }
1177 if ($action != 'edit_price_by_qty' && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
1178 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
1179 print '<input type="hidden" name="token" value="'.newToken().'">';
1180 print '<input type="hidden" name="action" value="update_price_by_qty">';
1181 print '<input type="hidden" name="priceid" value="'.$object->prices_by_qty_id[$i].'">'; // id in product_price
1182 print '<input type="hidden" value="0" name="rowid">'; // id in product_price
1183 print '<tr class="'.($ii % 2 == 0 ? 'pair' : 'impair').'">';
1184 print '<td><input size="5" type="text" value="1" name="quantity"></td>';
1185 print '<td class="right" class="nowrap"><input size="10" type="text" value="0" name="price">&nbsp;'.$object->price_base_type.'</td>';
1186 print '<td class="right">&nbsp;</td>';
1187 print '<td class="right" class="nowraponall"><input size="5" type="text" value="0" name="remise_percent"> %</td>';
1188 print '<td class="center"><input type="submit" value="'.$langs->trans("Add").'" class="button"></td>';
1189 print '</tr>';
1190 print '</form>';
1191 }
1192
1193 print '</table>';
1194 print '<a class="editfielda marginleftonly marginrightonly" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=disable_price_by_qty&level='.$i.'&token='.newToken().'">('.$langs->trans("DisablePriceByQty").')</a>';
1195 } else {
1196 print $langs->trans("No");
1197 print '&nbsp; <a class="marginleftonly marginrightonly" href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=activate_price_by_qty&level='.$i.'&token='.newToken().'">('.$langs->trans("Activate").')</a>';
1198 }
1199 print '</td></tr>';
1200 }
1201 }
1202 }
1203} else {
1204 // TVA
1205 print '<tr><td class="titlefield">'.$langs->trans("DefaultTaxRate").'</td><td>';
1206
1207 $positiverates = '';
1208 if (price2num($object->tva_tx)) {
1209 $positiverates .= ($positiverates ? '/' : '').price2num($object->tva_tx);
1210 }
1211 if (price2num($object->localtax1_type)) {
1212 $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax1_tx);
1213 }
1214 if (price2num($object->localtax2_type)) {
1215 $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax2_tx);
1216 }
1217 if (empty($positiverates)) {
1218 $positiverates = '0';
1219 }
1220 echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr, 0, 1);
1221 /*
1222 if ($object->default_vat_code)
1223 {
1224 print vatrate($object->tva_tx, true) . ' ('.$object->default_vat_code.')';
1225 }
1226 else print vatrate($object->tva_tx, true, $object->tva_npr, true);*/
1227 print '</td></tr>';
1228
1229 // Price
1230 print '<tr class="field_selling_price"><td>'.$langs->trans("SellingPrice").'</td><td>';
1231 if ($object->price_base_type == 'TTC') {
1232 print price($object->price_ttc).' '.$langs->trans($object->price_base_type);
1233 } else {
1234 print price($object->price).' '.$langs->trans($object->price_base_type);
1235 if (getDolGlobalString('PRODUCT_DISPLAY_VAT_INCL_PRICES') && !empty($object->price_ttc)) {
1236 print '<i class="opacitymedium"> - ' . price($object->price_ttc).' '.$langs->trans('TTC') . '</i>';
1237 }
1238 }
1239
1240 print '</td></tr>';
1241
1242 // Price minimum
1243 print '<tr class="field_min_price"><td>'.$langs->trans("MinPrice").'</td><td>';
1244 if ($object->price_base_type == 'TTC') {
1245 print price($object->price_min_ttc).' '.$langs->trans($object->price_base_type);
1246 } else {
1247 print price($object->price_min).' '.$langs->trans($object->price_base_type);
1248 if (getDolGlobalString('PRODUCT_DISPLAY_VAT_INCL_PRICES') && !empty($object->price_min_ttc)) {
1249 print '<i class="opacitymedium"> - ' . price($object->price_min_ttc).' '.$langs->trans('TTC') . '</i>';
1250 }
1251 }
1252 print '</td></tr>';
1253
1254 // Price Label
1255 print '<tr class="field_price_label"><td>'.$langs->trans("PriceLabel").'</td><td>';
1256 print $object->price_label;
1257 print '</td></tr>';
1258
1259 // Price by quantity
1260 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { // TODO Fix the form inside tr instead of td
1261 print '<tr><td>'.$langs->trans("PriceByQuantity");
1262 if ($object->prices_by_qty[0] == 0) {
1263 print '&nbsp; <a href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=activate_price_by_qty&level=1&token='.newToken().'">('.$langs->trans("Activate").')';
1264 } else {
1265 print '&nbsp; <a href="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'&action=disable_price_by_qty&level=1&token='.newToken().'">('.$langs->trans("DisablePriceByQty").')';
1266 }
1267 print '</td><td>';
1268
1269 if ($object->prices_by_qty[0] == 1) {
1270 print '<table width="50%" class="border" summary="List of quantities">';
1271 print '<tr class="liste_titre">';
1272 //print '<td>' . $langs->trans("PriceByQuantityRange") . '</td>';
1273 print '<td>'.$langs->trans("Quantity").'</td>';
1274 print '<td class="right">'.$langs->trans("Price").'</td>';
1275 print '<td class="right"></td>';
1276 print '<td class="right">'.$langs->trans("UnitPrice").'</td>';
1277 print '<td class="right">'.$langs->trans("Discount").'</td>';
1278 print '<td>&nbsp;</td>';
1279 print '</tr>';
1280 if ($action != 'edit_price_by_qty') {
1281 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">'; // FIXME a form into a table is not allowed
1282 print '<input type="hidden" name="token" value="'.newToken().'">';
1283 print '<input type="hidden" name="action" value="update_price_by_qty">';
1284 print '<input type="hidden" name="priceid" value="'.$object->prices_by_qty_id[0].'">'; // id in product_price
1285 print '<input type="hidden" value="0" name="rowid">'; // id in product_price_by_qty
1286
1287 print '<tr class="'.($ii % 2 == 0 ? 'pair' : 'impair').'">';
1288 print '<td><input size="5" type="text" value="1" name="quantity"></td>';
1289 print '<td class="right"><input class="width50 right" type="text" value="0" name="price"></td>';
1290 print '<td>';
1291 //print $object->price_base_type;
1292 print '</td>';
1293 print '<td class="right">&nbsp;</td>';
1294 print '<td class="right nowraponall"><input type="text" class="width50 right" value="0" name="remise_percent"> %</td>';
1295 print '<td class="center"><input type="submit" value="'.$langs->trans("Add").'" class="button"></td>';
1296 print '</tr>';
1297
1298 print '</form>';
1299 }
1300 foreach ($object->prices_by_qty_list[0] as $ii => $prices) {
1301 if ($action == 'edit_price_by_qty' && $rowid == $prices['rowid'] && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
1302 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
1303 print '<input type="hidden" name="token" value="'.newToken().'">';
1304 print '<input type="hidden" name="action" value="update_price_by_qty">';
1305 print '<input type="hidden" name="priceid" value="'.$object->prices_by_qty_id[0].'">'; // id in product_price
1306 print '<input type="hidden" value="'.$prices['rowid'].'" name="rowid">'; // id in product_price_by_qty
1307 print '<tr class="'.($ii % 2 == 0 ? 'pair' : 'impair').'">';
1308 print '<td><input size="5" type="text" value="'.$prices['quantity'].'" name="quantity"></td>';
1309 print '<td class="right"><input class="width50 right" type="text" value="'.price2num($prices['price'], 'MU').'" name="price"></td>';
1310 print '<td class="right">';
1311 //print $object->price_base_type;
1312 print $prices['price_base_type'];
1313 print '</td>';
1314 print '<td class="right">&nbsp;</td>';
1315 print '<td class="right nowraponall"><input class="width50 right" type="text" value="'.$prices['remise_percent'].'" name="remise_percent"> %</td>';
1316 print '<td class="center"><input type="submit" value="'.$langs->trans("Modify").'" class="button"></td>';
1317 print '</tr>';
1318 print '</form>';
1319 } else {
1320 print '<tr class="'.($ii % 2 == 0 ? 'pair' : 'impair').'">';
1321 print '<td>'.$prices['quantity'].'</td>';
1322 print '<td class="right">'.price($prices['price']).'</td>';
1323 print '<td class="right">';
1324 //print $object->price_base_type;
1325 print $prices['price_base_type'];
1326 print '</td>';
1327 print '<td class="right">'.price($prices['unitprice']).'</td>';
1328 print '<td class="right">'.price($prices['remise_percent']).' %</td>';
1329 print '<td class="center">';
1330 if (($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
1331 print '<a class="editfielda marginleftonly marginrightonly" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=edit_price_by_qty&token='.newToken().'&rowid='.$prices["rowid"].'">';
1332 print img_edit().'</a>';
1333 print '<a class="marginleftonly marginrightonly" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete_price_by_qty&token='.newToken().'&rowid='.$prices["rowid"].'">';
1334 print img_delete().'</a>';
1335 } else {
1336 print '&nbsp;';
1337 }
1338 print '</td>';
1339 print '</tr>';
1340 }
1341 }
1342 print '</table>';
1343 } else {
1344 print $langs->trans("No");
1345 }
1346 print '</td></tr>';
1347 }
1348}
1349
1350print "</table>\n";
1351
1352print '</div>';
1353print '<div class="clearboth"></div>';
1354
1355
1356print dol_get_fiche_end();
1357
1358
1359
1360/*
1361 * Action bar
1362 */
1363
1364
1365if (!$action || $action == 'delete' || $action == 'showlog_customer_price' || $action == 'showlog_default_price' || $action == 'add_customer_price'
1366 || $action == 'activate_price_by_qty' || $action == 'disable_price_by_qty') {
1367 print "\n".'<div class="tabsAction">'."\n";
1368
1369
1370 $parameters = array();
1371 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1372 if (empty($reshook)) {
1373 if ($object->isVariant()) {
1374 if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) {
1375 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("NoEditVariants")) . '">' . $langs->trans("UpdateDefaultPrice") . '</a></div>';
1376 }
1377 } else {
1378 if (!getDolGlobalString('PRODUIT_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1379 if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) {
1380 print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?action=edit_price&token='.newToken().'&id=' . $object->id . '">' . $langs->trans("UpdateDefaultPrice") . '</a></div>';
1381 } else {
1382 print '<div class="inline-block divButAction"><span class="butActionRefused" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">' . $langs->trans("UpdateDefaultPrice") . '</span></div>';
1383 }
1384 }
1385
1386 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1387 if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) {
1388 print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?action=add_customer_price&token='.newToken().'&id=' . $object->id . '">' . $langs->trans("AddCustomerPrice") . '</a></div>';
1389 } else {
1390 print '<div class="inline-block divButAction"><span class="butActionRefused" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">' . $langs->trans("AddCustomerPrice") . '</span></div>';
1391 }
1392 }
1393
1394 if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1395 if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) {
1396 print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?action=edit_vat&token='.newToken().'&id=' . $object->id . '">' . $langs->trans("UpdateVAT") . '</a></div>';
1397 } else {
1398 print '<div class="inline-block divButAction"><span class="butActionRefused" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">' . $langs->trans("UpdateVAT") . '</span></div>';
1399 }
1400
1401 if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) {
1402 print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?action=edit_level_price&token='.newToken().'&id=' . $object->id . '">' . $langs->trans("UpdateLevelPrices") . '</a></div>';
1403 } else {
1404 print '<div class="inline-block divButAction"><span class="butActionRefused" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">' . $langs->trans("UpdateLevelPrices") . '</span></div>';
1405 }
1406 }
1407 }
1408 }
1409
1410 print "\n</div>\n";
1411}
1412
1413
1414
1415/*
1416 * Edit price area
1417 */
1418
1419if ($action == 'edit_vat' && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
1420 print load_fiche_titre($langs->trans("UpdateVAT"), '');
1421
1422 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
1423 print '<input type="hidden" name="token" value="'.newToken().'">';
1424 print '<input type="hidden" name="action" value="update_vat">';
1425 print '<input type="hidden" name="id" value="'.$object->id.'">';
1426
1427 print dol_get_fiche_head();
1428
1429 print '<table class="border centpercent">';
1430
1431 // VAT
1432 print '<tr><td>'.$langs->trans("DefaultTaxRate").'</td><td>';
1433 print $form->load_tva("tva_tx", $object->default_vat_code ? $object->tva_tx.' ('.$object->default_vat_code.')' : $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr, $object->type, false, 1);
1434 print '</td></tr>';
1435
1436 print '</table>';
1437
1438 print dol_get_fiche_end();
1439
1440 print $form->buttonsSaveCancel();
1441
1442 print '<br></form><br>';
1443}
1444
1445if (($action == 'edit_price' || $action == 'edit_level_price') && $object->getRights()->creer) {
1446 print '<br>';
1447 print load_fiche_titre($langs->trans("NewPrice"), '');
1448
1449 if (!getDolGlobalString('PRODUIT_MULTIPRICES') && $action != 'edit_level_price') {
1450 print '<!-- Edit price -->'."\n";
1451 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
1452 print '<input type="hidden" name="token" value="'.newToken().'">';
1453 print '<input type="hidden" name="action" value="update_price">';
1454 print '<input type="hidden" name="id" value="'.$object->id.'">';
1455
1456 print dol_get_fiche_head();
1457
1458 print '<div class="div-table-responsive-no-min">';
1459 print '<table class="border centpercent">';
1460
1461 // VAT
1462 print '<tr><td class="titlefield">'.$langs->trans("DefaultTaxRate").'</td><td>';
1463 print $form->load_tva("tva_tx", $object->default_vat_code ? $object->tva_tx.' ('.$object->default_vat_code.')' : $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr, $object->type, false, 1);
1464 print '</td></tr>';
1465
1466 // Price base
1467 print '<tr><td>';
1468 print $langs->trans('PriceBase');
1469 print '</td>';
1470 print '<td>';
1471 print $form->selectPriceBaseType($object->price_base_type, "price_base_type");
1472 print '</td>';
1473 print '</tr>';
1474
1475 // Only show price mode and expression selector if module is enabled
1476 if (!empty($conf->dynamicprices->enabled)) {
1477 // Price mode selector
1478 print '<!-- Show price mode of dynamicprices editor -->'."\n";
1479 print '<tr><td>'.$langs->trans("PriceMode").'</td><td>';
1480 print img_picto('', 'dynamicprice', 'class="pictofixedwidth"');
1481 $price_expression = new PriceExpression($db);
1482 $price_expression_list = array(0 => $langs->trans("Numeric").' <span class="opacitymedium">('.$langs->trans("NoDynamicPrice").')</span>'); //Put the numeric mode as first option
1483 foreach ($price_expression->list_price_expression() as $entry) {
1484 $price_expression_list[$entry->id] = $entry->title;
1485 }
1486 $price_expression_preselection = GETPOST('eid') ? GETPOST('eid') : ($object->fk_price_expression ? $object->fk_price_expression : '0');
1487 print $form->selectarray('eid', $price_expression_list, $price_expression_preselection);
1488 print '&nbsp; <a id="expression_editor" class="classlink">'.$langs->trans("PriceExpressionEditor").'</a>';
1489 print '</td></tr>';
1490
1491 // This code hides the numeric price input if is not selected, loads the editor page if editor button is pressed
1492 ?>
1493
1494 <script type="text/javascript">
1495 jQuery(document).ready(function() {
1496 jQuery("#expression_editor").click(function() {
1497 window.location = "<?php echo DOL_URL_ROOT ?>/product/dynamic_price/editor.php?id=<?php echo $id ?>&tab=price&eid=" + $("#eid").val();
1498 });
1499 jQuery("#eid").change(on_change);
1500 on_change();
1501 });
1502 function on_change() {
1503 if ($("#eid").val() == 0) {
1504 jQuery("#price_numeric").show();
1505 } else {
1506 jQuery("#price_numeric").hide();
1507 }
1508 }
1509 </script>
1510 <?php
1511 }
1512
1513 // Price
1514 $product = new Product($db);
1515 $product->fetch($id, $ref, '', 1); //Ignore the math expression when getting the price
1516 print '<tr id="price_numeric"><td>';
1517 $text = $langs->trans('SellingPrice');
1518 print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1);
1519 print '</td><td>';
1520 if ($object->price_base_type == 'TTC') {
1521 print '<input name="price" size="10" value="'.price($product->price_ttc).'">';
1522 } else {
1523 print '<input name="price" size="10" value="'.price($product->price).'">';
1524 }
1525 print '</td></tr>';
1526
1527 // Price minimum
1528 print '<tr><td>';
1529 $text = $langs->trans('MinPrice');
1530 print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1);
1531 print '</td><td>';
1532 if ($object->price_base_type == 'TTC') {
1533 print '<input name="price_min" size="10" value="'.price($object->price_min_ttc).'">';
1534 } else {
1535 print '<input name="price_min" size="10" value="'.price($object->price_min).'">';
1536 }
1537 if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) {
1538 print ' &nbsp; '.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')).' '.img_warning().'</td>';
1539 }
1540 print '</td>';
1541 print '</tr>';
1542
1543 // Price Label
1544 print '<tr><td>';
1545 print $langs->trans('PriceLabel');
1546 print '</td><td>';
1547 print '<input name="price_label" maxlength="255" class="minwidth300 maxwidth400onsmartphone" value="'.$object->price_label.'">';
1548 print '</td>';
1549 print '</tr>';
1550
1551 $parameters = array();
1552 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1553
1554 print '</table>';
1555 print '</div>';
1556
1557 print dol_get_fiche_end();
1558
1559 print $form->buttonsSaveCancel();
1560
1561 print '</form>';
1562 } elseif ($action == 'edit_level_price' && $object->getRights()->creer) {
1563 print '<!-- Edit price per level -->'."\n"; ?>
1564 <script>
1565
1566 var showHidePriceRules = function () {
1567 var otherPrices = $('div.fiche form table tbody tr:not(:first)');
1568 var minPrice1 = $('div.fiche form input[name="price_min[1]"]');
1569
1570 if (jQuery('input#usePriceRules').prop('checked')) {
1571 otherPrices.hide();
1572 minPrice1.hide();
1573 } else {
1574 otherPrices.show();
1575 minPrice1.show();
1576 }
1577 }
1578
1579 jQuery(document).ready(function () {
1580 showHidePriceRules();
1581
1582 jQuery('input#usePriceRules').click(showHidePriceRules);
1583 });
1584 </script>
1585 <?php
1586
1587 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
1588 print '<input type="hidden" name="token" value="'.newToken().'">';
1589 print '<input type="hidden" name="action" value="update_level_price">';
1590 print '<input type="hidden" name="id" value="'.$object->id.'">';
1591
1592 //print dol_get_fiche_head(array(), '', '', -1);
1593
1594 if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && getDolGlobalString('PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL')) {
1595 print $langs->trans('UseMultipriceRules').' <input type="checkbox" id="usePriceRules" name="usePriceRules" '.($object->price_autogen ? 'checked' : '').'><br><br>';
1596 }
1597
1598 print '<div class="div-table-responsive-no-min">';
1599 print '<table class="noborder">';
1600 print '<thead><tr class="liste_titre">';
1601
1602 print '<td>'.$langs->trans("PriceLevel").'</td>';
1603
1604 if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) {
1605 print '<td style="text-align: center">'.$langs->trans("DefaultTaxRate").'</td>';
1606 } else {
1607 print '<td></td>';
1608 }
1609
1610 print '<td class="center">'.$langs->trans("SellingPrice").'</td>';
1611
1612 print '<td class="center">'.$langs->trans("MinPrice").'</td>';
1613
1614 if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) {
1615 print '<td></td>';
1616 }
1617 print '</tr></thead>';
1618
1619 print '<tbody>';
1620
1621 $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT');
1622 for ($i = 1; $i <= $produit_multiprices_limit; $i++) {
1623 print '<tr class="oddeven">';
1624 print '<td>';
1625 $keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.$i;
1626 $text = $langs->trans('SellingPrice').' '.$i.' - '.getDolGlobalString($keyforlabel);
1627 print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1);
1628 print '</td>';
1629
1630 // VAT
1631 if (!getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) {
1632 print '<td>';
1633 print '<input type="hidden" name="tva_tx['.$i.']" value="'.($object->default_vat_code ? $object->tva_tx.' ('.$object->default_vat_code.')' : $object->tva_tx).'">';
1634 print '<input type="hidden" name="tva_npr['.$i.']" value="'.$object->tva_npr.'">';
1635 print '<input type="hidden" name="localtax1_tx['.$i.']" value="'.$object->localtax1_tx.'">';
1636 print '<input type="hidden" name="localtax1_type['.$i.']" value="'.$object->localtax1_type.'">';
1637 print '<input type="hidden" name="localtax2_tx['.$i.']" value="'.$object->localtax2_tx.'">';
1638 print '<input type="hidden" name="localtax2_type['.$i.']" value="'.$object->localtax2_type.'">';
1639 print '</td>';
1640 } else {
1641 // This option is kept for backward compatibility but has no sense
1642 print '<td style="text-align: center">';
1643 print $form->load_tva("tva_tx[".$i.']', $object->multiprices_tva_tx[$i], $mysoc, '', $object->id, false, $object->type, false, 1);
1644 print '</td>';
1645 }
1646
1647 // Selling price
1648 print '<td style="text-align: center">';
1649 if ($object->multiprices_base_type [$i] == 'TTC') {
1650 print '<input name="price['.$i.']" size="10" value="'.price($object->multiprices_ttc [$i]).'">';
1651 } else {
1652 print '<input name="price['.$i.']" size="10" value="'.price($object->multiprices [$i]).'">';
1653 }
1654 print '&nbsp;'.$form->selectPriceBaseType($object->multiprices_base_type [$i], "multiprices_base_type[".$i."]");
1655 print '</td>';
1656
1657 // Min price
1658 print '<td style="text-align: center">';
1659 if ($object->multiprices_base_type [$i] == 'TTC') {
1660 print '<input name="price_min['.$i.']" size="10" value="'.price($object->multiprices_min_ttc [$i]).'">';
1661 } else {
1662 print '<input name="price_min['.$i.']" size="10" value="'.price($object->multiprices_min [$i]).'">';
1663 }
1664 if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) {
1665 print '<td class="left">'.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')).' '.img_warning().'</td>';
1666 }
1667 print '</td>';
1668
1669 print '</tr>';
1670 }
1671
1672 print '</tbody>';
1673
1674 print '</table>';
1675 print '</div>';
1676
1677 //print dol_get_fiche_end();
1678
1679 print $form->buttonsSaveCancel();
1680
1681 print '</form>';
1682 }
1683}
1684
1685// Add area to show/add/edit a price for a dedicated customer
1686if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
1687 $prodcustprice = new ProductCustomerPrice($db);
1688
1689 $limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
1690 $sortfield = GETPOST('sortfield', 'aZ09comma');
1691 $sortorder = GETPOST('sortorder', 'aZ09comma');
1692 $page = (GETPOSTINT("page") ? GETPOSTINT("page") : 0);
1693 if (empty($page) || $page == -1) {
1694 $page = 0;
1695 } // If $page is not defined, or '' or -1
1696 $offset = $limit * $page;
1697 $pageprev = $page - 1;
1698 $pagenext = $page + 1;
1699 if (!$sortorder) {
1700 $sortorder = "ASC";
1701 }
1702 if (!$sortfield) {
1703 $sortfield = "soc.nom";
1704 }
1705
1706 // Build filter to display only concerned lines
1707 $filter = array('t.fk_product' => $object->id);
1708
1709 if (!empty($search_soc)) {
1710 $filter['soc.nom'] = $search_soc;
1711 }
1712
1713 if ($action == 'add_customer_price') {
1714 // Form to add a new customer price
1715 $maxpricesupplier = $object->min_recommended_price();
1716
1717 print '<!-- add_customer_price -->';
1718 print load_fiche_titre($langs->trans('AddCustomerPrice'));
1719
1720 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
1721 print '<input type="hidden" name="token" value="'.newToken().'">';
1722 print '<input type="hidden" name="action" value="add_customer_price_confirm">';
1723 print '<input type="hidden" name="id" value="'.$object->id.'">';
1724
1725 print '<div class="tabBar tabBarWithBottom">';
1726
1727 print '<table class="border centpercent">';
1728 print '<tr>';
1729 print '<td class="fieldrequired">'.$langs->trans('ThirdParty').'</td>';
1730 print '<td>';
1731 $filter = '(s.client:IN:1,2,3)';
1732 print img_picto('', 'company').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300');
1733 print '</td>';
1734 print '</tr>';
1735
1736 // Ref. Customer
1737 print '<tr><td>' . $langs->trans('RefCustomer') . '</td>';
1738 print '<td><input name="ref_customer" size="12"></td></tr>';
1739
1740 // VAT
1741 print '<tr><td class="fieldrequired">'.$langs->trans("DefaultTaxRate").'</td><td>';
1742 print $form->load_tva("tva_tx", $object->default_vat_code ? $object->tva_tx.' ('.$object->default_vat_code.')' : $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr, $object->type, false, 1);
1743 print '</td></tr>';
1744
1745 // Price base
1746 print '<tr><td class="fieldrequired">';
1747 print $langs->trans('PriceBase');
1748 print '</td>';
1749 print '<td>';
1750 print $form->selectPriceBaseType($object->price_base_type, "price_base_type");
1751 print '</td>';
1752 print '</tr>';
1753
1754 // Price
1755 print '<tr><td class="fieldrequired">';
1756 $text = $langs->trans('SellingPrice');
1757 print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1);
1758 print '</td><td>';
1759 if ($object->price_base_type == 'TTC') {
1760 print '<input name="price" size="10" value="'.price($object->price_ttc).'">';
1761 } else {
1762 print '<input name="price" size="10" value="'.price($object->price).'">';
1763 }
1764 print '</td></tr>';
1765
1766 // Price minimum
1767 print '<tr><td>';
1768 $text = $langs->trans('MinPrice');
1769 print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1);
1770 if ($object->price_base_type == 'TTC') {
1771 print '<td><input name="price_min" size="10" value="'.price($object->price_min_ttc).'">';
1772 } else {
1773 print '<td><input name="price_min" size="10" value="'.price($object->price_min).'">';
1774 }
1775 if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) {
1776 print '<td class="left">'.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')).' '.img_warning().'</td>';
1777 }
1778 print '</td></tr>';
1779
1780 // Price Label
1781 print '<tr><td>';
1782 print $langs->trans('PriceLabel');
1783 print '</td><td>';
1784 print '<input name="price_label" maxlength="255" class="minwidth300 maxwidth400onsmartphone" value="'.$object->price_label.'">';
1785 print '</td>';
1786 print '</tr>';
1787
1788 print '</table>';
1789
1790 print '</div>';
1791
1792
1793 print '<div class="center">';
1794
1795 // Update all child soc
1796 print '<div class="marginbottomonly">';
1797 print '<input type="checkbox" name="updatechildprice" id="updatechildprice" value="1"> ';
1798 print '<label for="updatechildprice">'.$langs->trans('ForceUpdateChildPriceSoc').'</label>';
1799 print '</div>';
1800
1801 print $form->buttonsSaveCancel();
1802
1803 print '</form>';
1804 } elseif ($action == 'edit_customer_price') {
1805 // Edit mode
1806 $maxpricesupplier = $object->min_recommended_price();
1807
1808 print '<!-- edit_customer_price -->';
1809 print load_fiche_titre($langs->trans('PriceByCustomer'));
1810
1811 $result = $prodcustprice->fetch(GETPOSTINT('lineid'));
1812 if ($result < 0) {
1813 setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
1814 }
1815
1816 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
1817 print '<input type="hidden" name="token" value="'.newToken().'">';
1818 print '<input type="hidden" name="action" value="update_customer_price_confirm">';
1819 print '<input type="hidden" name="lineid" value="'.$prodcustprice->id.'">';
1820
1821 print '<table class="liste centpercent">';
1822 print '<tr>';
1823 print '<td class="titlefield fieldrequired">'.$langs->trans('ThirdParty').'</td>';
1824 $staticsoc = new Societe($db);
1825 $staticsoc->fetch($prodcustprice->fk_soc);
1826 print "<td>".$staticsoc->getNomUrl(1)."</td>";
1827 print '</tr>';
1828
1829 // Ref. Customer
1830 print '<tr><td>' . $langs->trans('RefCustomer') . '</td>';
1831 print '<td><input name="ref_customer" size="12" value="' . dol_escape_htmltag($prodcustprice->ref_customer) . '"></td></tr>';
1832
1833 // VAT
1834 print '<tr><td class="fieldrequired">'.$langs->trans("DefaultTaxRate").'</td><td>';
1835 print $form->load_tva("tva_tx", $prodcustprice->default_vat_code ? $prodcustprice->tva_tx.' ('.$prodcustprice->default_vat_code.')' : $prodcustprice->tva_tx, $mysoc, '', $object->id, $prodcustprice->recuperableonly, $object->type, false, 1);
1836 print '</td></tr>';
1837
1838 // Price base
1839 print '<tr><td class="fieldrequired">';
1840 print $langs->trans('PriceBase');
1841 print '</td>';
1842 print '<td>';
1843 print $form->selectPriceBaseType($prodcustprice->price_base_type, "price_base_type");
1844 print '</td>';
1845 print '</tr>';
1846
1847 // Price
1848 print '<tr><td class="fieldrequired">';
1849 $text = $langs->trans('SellingPrice');
1850 print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1);
1851 print '</td><td>';
1852 if ($prodcustprice->price_base_type == 'TTC') {
1853 print '<input name="price" size="10" value="'.price($prodcustprice->price_ttc).'">';
1854 } else {
1855 print '<input name="price" size="10" value="'.price($prodcustprice->price).'">';
1856 }
1857 print '</td></tr>';
1858
1859 // Price minimum
1860 print '<tr><td>';
1861 $text = $langs->trans('MinPrice');
1862 print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1);
1863 print '</td><td>';
1864 if ($prodcustprice->price_base_type == 'TTC') {
1865 print '<input name="price_min" size="10" value="'.price($prodcustprice->price_min_ttc).'">';
1866 } else {
1867 print '<input name="price_min" size="10" value="'.price($prodcustprice->price_min).'">';
1868 }
1869 print '</td>';
1870 if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) {
1871 print '<td class="left">'.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')).' '.img_warning().'</td>';
1872 }
1873 print '</tr>';
1874
1875
1876
1877 // Price Label
1878 print '<tr><td>';
1879 print $langs->trans('PriceLabel');
1880 print '</td><td>';
1881 print '<input name="price_label" maxlength="255" class="minwidth300 maxwidth400onsmartphone" value="'.$prodcustprice->price_label.'">';
1882 print '</td>';
1883 print '</tr>';
1884
1885 print '</table>';
1886
1887
1888 print '<div class="center">';
1889 print '<div class="marginbottomonly">';
1890 print '<input type="checkbox" name="updatechildprice" id="updatechildprice" value="1"> ';
1891 print '<label for="updatechildprice">'.$langs->trans('ForceUpdateChildPriceSoc').'</label>';
1892 print "</div>";
1893
1894 print $form->buttonsSaveCancel();
1895
1896 print '<br></form>';
1897 } elseif ($action == 'showlog_customer_price') {
1898 // List of all log of prices by customers
1899 print '<!-- list of all log of prices per customer -->'."\n";
1900
1901 $filter = array('t.fk_product' => $object->id, 't.fk_soc' => GETPOSTINT('socid'));
1902
1903 // Count total nb of records
1904 $nbtotalofrecords = '';
1905 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
1906 $nbtotalofrecords = $prodcustprice->fetchAllLog($sortorder, $sortfield, $conf->liste_limit, $offset, $filter);
1907 }
1908
1909 $result = $prodcustprice->fetchAllLog($sortorder, $sortfield, $conf->liste_limit, $offset, $filter);
1910 if ($result < 0) {
1911 setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
1912 }
1913
1914 $option = '&socid='.GETPOSTINT('socid').'&id='.$object->id;
1915
1916 $staticsoc = new Societe($db);
1917 $staticsoc->fetch(GETPOSTINT('socid'));
1918
1919 $title = $langs->trans('PriceByCustomerLog');
1920 $title .= ' - '.$staticsoc->getNomUrl(1);
1921
1922 $backbutton = '<a class="justalink" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">'.$langs->trans("Back").'</a>';
1923
1924 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
1925 print_barre_liste($title, $page, $_SERVER['PHP_SELF'], $option, $sortfield, $sortorder, $backbutton, count($prodcustprice->lines), $nbtotalofrecords, 'title_accountancy.png');
1926
1927 if (count($prodcustprice->lines) > 0) {
1928 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
1929 print '<input type="hidden" name="token" value="'.newToken().'">';
1930 print '<input type="hidden" name="id" value="'.$object->id.'">';
1931
1932 print '<div class="div-table-responsive-no-min">';
1933 print '<table class="liste centpercent">';
1934
1935 print '<tr class="liste_titre">';
1936 print '<td>'.$langs->trans("ThirdParty").'</td>';
1937 print '<td>'.$langs->trans('RefCustomer').'</td>';
1938 print '<td>'.$langs->trans("AppliedPricesFrom").'</td>';
1939 print '<td class="center">'.$langs->trans("PriceBase").'</td>';
1940 print '<td class="right">'.$langs->trans("DefaultTaxRate").'</td>';
1941 print '<td class="right">'.$langs->trans("HT").'</td>';
1942 print '<td class="right">'.$langs->trans("TTC").'</td>';
1943 if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
1944 print '<td class="right">'.$langs->trans("INCT").'</td>';
1945 }
1946 print '<td class="right">'.$langs->trans("MinPrice").' '.$langs->trans("HT").'</td>';
1947 print '<td class="right">'.$langs->trans("MinPrice").' '.$langs->trans("TTC").'</td>';
1948 print '<td class="right">'.$langs->trans("PriceLabel").'</td>';
1949 print '<td class="right">'.$langs->trans("ChangedBy").'</td>';
1950 print '<td>&nbsp;</td>';
1951 print '</tr>';
1952
1953 foreach ($prodcustprice->lines as $line) {
1954 // Date
1955 $staticsoc = new Societe($db);
1956 $staticsoc->fetch($line->fk_soc);
1957
1958 $tva_tx = $line->default_vat_code ? $line->tva_tx.' ('.$line->default_vat_code.')' : $line->tva_tx;
1959
1960 // Line for default price
1961 if ($line->price_base_type == 'HT') {
1962 $pu = $line->price;
1963 } else {
1964 $pu = $line->price_ttc;
1965 }
1966
1967 // Local tax is not saved into table of product. We use value linked to VAT code.
1968 $localtaxarray = getLocalTaxesFromRate($line->tva_tx.($line->default_vat_code ? ' ('.$line->default_vat_code.')' : ''), 0, $staticsoc, $mysoc);
1969 // Define part of HT, VAT, TTC
1970 $resultarray = calcul_price_total(1, $pu, 0, $line->tva_tx, 1, 1, 0, $line->price_base_type, $line->recuperableonly, $object->type, $mysoc, $localtaxarray);
1971 // Calcul du total ht sans remise
1972 $total_ht = $resultarray[0];
1973 $total_vat = $resultarray[1];
1974 $total_localtax1 = $resultarray[9];
1975 $total_localtax2 = $resultarray[10];
1976 $total_ttc = $resultarray[2];
1977
1978 print '<tr class="oddeven">';
1979
1980 print '<td class="tdoverflowmax125">'.$staticsoc->getNomUrl(1)."</td>";
1981 print '<td>'.$line->ref_customer.'</td>';
1982 print "<td>".dol_print_date($line->datec, "dayhour", 'tzuserrel')."</td>";
1983 print '<td class="center">'.$langs->trans($line->price_base_type)."</td>";
1984 print '<td class="right">';
1985
1986 $positiverates = '';
1987 if (price2num($line->tva_tx)) {
1988 $positiverates .= ($positiverates ? '/' : '').price2num($line->tva_tx);
1989 }
1990 if (price2num($line->localtax1_type)) {
1991 $positiverates .= ($positiverates ? '/' : '').price2num($line->localtax1_tx);
1992 }
1993 if (price2num($line->localtax2_type)) {
1994 $positiverates .= ($positiverates ? '/' : '').price2num($line->localtax2_tx);
1995 }
1996 if (empty($positiverates)) {
1997 $positiverates = '0';
1998 }
1999
2000 echo vatrate($positiverates.($line->default_vat_code ? ' ('.$line->default_vat_code.')' : ''), true, ($line->tva_npr ? $line->tva_npr : $line->recuperableonly));
2001
2002 //. vatrate($tva_tx, true, $line->recuperableonly) .
2003 print "</td>";
2004 print '<td class="right"><span class="amount">'.price($line->price)."</span></td>";
2005
2006 print '<td class="right"><span class="amount">'.price($line->price_ttc)."</span></td>";
2007 if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
2008 print '<td class="right">'.price($resultarray[2]).'</td>';
2009 }
2010
2011 print '<td class="right">'.price($line->price_min).'</td>';
2012 print '<td class="right">'.price($line->price_min_ttc).'</td>';
2013 print '<td class="right">'.$line->price_label.'</td>';
2014
2015 // User
2016 $userstatic = new User($db);
2017 $userstatic->fetch($line->fk_user);
2018 print '<td class="right">';
2019 print $userstatic->getNomUrl(1, '', 0, 0, 24, 0, 'login');
2020 //print $userstatic->getLoginUrl(1);
2021 print '</td>';
2022 print '</tr>';
2023 }
2024 print "</table>";
2025 print '</div>';
2026 } else {
2027 print $langs->trans('None');
2028 }
2029 } elseif ($action != 'showlog_default_price' && $action != 'edit_price' && $action != 'edit_level_price') {
2030 // List of all prices by customers
2031 print '<!-- list of all prices per customer -->'."\n";
2032
2033 // Count total nb of records
2034 $nbtotalofrecords = '';
2035 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
2036 $nbtotalofrecords = $prodcustprice->fetchAll($sortorder, $sortfield, 0, 0, $filter);
2037 }
2038
2039 $result = $prodcustprice->fetchAll($sortorder, $sortfield, $conf->liste_limit, $offset, $filter);
2040 if ($result < 0) {
2041 setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
2042 }
2043
2044 $option = '&search_soc='.$search_soc.'&id='.$object->id;
2045
2046 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
2047 print_barre_liste($langs->trans('PriceByCustomer'), $page, $_SERVER ['PHP_SELF'], $option, $sortfield, $sortorder, '', count($prodcustprice->lines), $nbtotalofrecords, 'title_accountancy.png');
2048
2049 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">';
2050 print '<input type="hidden" name="token" value="'.newToken().'">';
2051 print '<input type="hidden" name="id" value="'.$object->id.'">';
2052
2053 print '<!-- List of prices per customer -->'."\n";
2054 print '<div class="div-table-responsive-no-min">'."\n";
2055 print '<table class="liste centpercent">'."\n";
2056
2057 if (count($prodcustprice->lines) > 0 || $search_soc) {
2058 $colspan = 10;
2059 if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
2060 $colspan++;
2061 }
2062
2063 print '<tr class="liste_titre">';
2064 print '<td class="liste_titre"><input type="text" class="flat maxwidth125" name="search_soc" value="'.$search_soc.'"></td>';
2065 print '<td class="liste_titre" colspan="'.$colspan.'">&nbsp;</td>';
2066 // Print the search button
2067 print '<td class="liste_titre maxwidthsearch">';
2068 $searchpicto = $form->showFilterAndCheckAddButtons(0);
2069 print $searchpicto;
2070 print '</td>';
2071 print '</tr>';
2072 }
2073
2074 print '<tr class="liste_titre">';
2075 print '<td>'.$langs->trans("ThirdParty").'</td>';
2076 print '<td>'.$langs->trans('RefCustomer').'</td>';
2077 print '<td>'.$langs->trans("AppliedPricesFrom").'</td>';
2078 print '<td class="center">'.$langs->trans("PriceBase").'</td>';
2079 print '<td class="right">'.$langs->trans("DefaultTaxRate").'</td>';
2080 print '<td class="right">'.$langs->trans("HT").'</td>';
2081 print '<td class="right">'.$langs->trans("TTC").'</td>';
2082 if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
2083 print '<td class="right">'.$langs->trans("INCT").'</td>';
2084 }
2085 print '<td class="right">'.$langs->trans("MinPrice").' '.$langs->trans("HT").'</td>';
2086 print '<td class="right">'.$langs->trans("MinPrice").' '.$langs->trans("TTC").'</td>';
2087 print '<td class="right">'.$langs->trans("PriceLabel").'</td>';
2088 print '<td>'.$langs->trans("ChangedBy").'</td>';
2089 print '<td></td>';
2090 print '</tr>';
2091
2092 // Line for default price
2093 if ($object->price_base_type == 'HT') {
2094 $pu = $object->price;
2095 } else {
2096 $pu = $object->price_ttc;
2097 }
2098
2099 // Local tax was not saved into table llx_product on old versions. So we will use the value linked to the VAT code.
2100 $localtaxarray = getLocalTaxesFromRate($object->tva_tx.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), 0, $mysoc, $mysoc);
2101 // Define part of HT, VAT, TTC
2102 $resultarray = calcul_price_total(1, $pu, 0, $object->tva_tx, 1, 1, 0, $object->price_base_type, 0, $object->type, $mysoc, $localtaxarray);
2103 // Calcul du total ht sans remise
2104 $total_ht = $resultarray[0];
2105 $total_vat = $resultarray[1];
2106 $total_localtax1 = $resultarray[9];
2107 $total_localtax2 = $resultarray[10];
2108 $total_ttc = $resultarray[2];
2109
2110 if (!getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
2111 print '<tr class="oddeven">';
2112 print '<td colspan="3">' . $langs->trans('Default') . '</td>';
2113
2114 print '<td class="center">'.$langs->trans($object->price_base_type)."</td>";
2115
2116 // VAT Rate
2117 print '<td class="right">';
2118
2119 $positiverates = '';
2120 if (price2num($object->tva_tx)) {
2121 $positiverates .= ($positiverates ? '/' : '').price2num($object->tva_tx);
2122 }
2123 if (price2num($object->localtax1_type)) {
2124 $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax1_tx);
2125 }
2126 if (price2num($object->localtax2_type)) {
2127 $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax2_tx);
2128 }
2129 if (empty($positiverates)) {
2130 $positiverates = '0';
2131 }
2132 echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr);
2133
2134 //print vatrate($object->tva_tx, true, $object->tva_npr);
2135 //print $object->default_vat_code?' ('.$object->default_vat_code.')':'';
2136 print "</td>";
2137
2138 print '<td class="right"><span class="amount">'.price($object->price)."</span></td>";
2139
2140 print '<td class="right"><span class="amount">'.price($object->price_ttc)."</span></td>";
2141 if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
2142 //print '<td class="right">' . price($object->price_ttc) . "</td>";
2143 print '<td class="right"><span class="amount">'.price($resultarray[2]).'</span></td>';
2144 }
2145
2146 print '<td class="right">'.price($object->price_min).'</td>';
2147 print '<td class="right">'.price($object->price_min_ttc).'</td>';
2148 print '<td class="right">'.$object->price_label.'</td>';
2149 print '<td class="right">';
2150 print '</td>';
2151 if ($user->hasRight('produit', 'supprimer') || $user->hasRight('service', 'supprimer')) {
2152 print '<td class="nowraponall">';
2153 print '<a class="marginleftonly marginrightonly" href="'.$_SERVER["PHP_SELF"].'?action=showlog_default_price&token='.newToken().'&id='.$object->id.'">';
2154 print img_info($langs->trans('PriceByCustomerLog'));
2155 print '</a>';
2156 print ' ';
2157 print '<a class="marginleftonly marginrightonly editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edit_price&token='.newToken().'&id='.$object->id.'">';
2158 print img_edit('default', 0, 'style="vertical-align: middle;"');
2159 print '</a>';
2160 print '</td>';
2161 }
2162 print "</tr>\n";
2163 }
2164
2165 if (count($prodcustprice->lines) > 0) {
2166 foreach ($prodcustprice->lines as $line) {
2167 // Date
2168 $staticsoc = new Societe($db);
2169 $staticsoc->fetch($line->fk_soc);
2170
2171 $tva_tx = $line->default_vat_code ? $line->tva_tx.' ('.$line->default_vat_code.')' : $line->tva_tx;
2172
2173 // Line for default price
2174 if ($line->price_base_type == 'HT') {
2175 $pu = $line->price;
2176 } else {
2177 $pu = $line->price_ttc;
2178 }
2179
2180 // Local tax is not saved into table of product. We use value linked to VAT code.
2181 $localtaxarray = getLocalTaxesFromRate($line->tva_tx.($line->default_vat_code ? ' ('.$line->default_vat_code.')' : ''), 0, $staticsoc, $mysoc);
2182 // Define part of HT, VAT, TTC
2183 $resultarray = calcul_price_total(1, $pu, 0, $line->tva_tx, 1, 1, 0, $line->price_base_type, $line->recuperableonly, $object->type, $mysoc, $localtaxarray);
2184 // Calcul du total ht sans remise
2185 $total_ht = $resultarray[0];
2186 $total_vat = $resultarray[1];
2187 $total_localtax1 = $resultarray[9];
2188 $total_localtax2 = $resultarray[10];
2189 $total_ttc = $resultarray[2];
2190
2191 print '<tr class="oddeven">';
2192
2193 print '<td class="tdoverflowmax125">'.$staticsoc->getNomUrl(1)."</td>";
2194 print '<td>'.dol_escape_htmltag($line->ref_customer).'</td>';
2195 print "<td>".dol_print_date($line->datec, "dayhour", 'tzuserrel')."</td>";
2196 print '<td class="center">'.$langs->trans($line->price_base_type)."</td>";
2197 // VAT Rate
2198 print '<td class="right">';
2199
2200 $positiverates = '';
2201 if (price2num($line->tva_tx)) {
2202 $positiverates .= ($positiverates ? '/' : '').price2num($line->tva_tx);
2203 }
2204 if (price2num($line->localtax1_type)) {
2205 $positiverates .= ($positiverates ? '/' : '').price2num($line->localtax1_tx);
2206 }
2207 if (price2num($line->localtax2_type)) {
2208 $positiverates .= ($positiverates ? '/' : '').price2num($line->localtax2_tx);
2209 }
2210 if (empty($positiverates)) {
2211 $positiverates = '0';
2212 }
2213
2214 echo vatrate($positiverates.($line->default_vat_code ? ' ('.$line->default_vat_code.')' : ''), true, (!empty($line->tva_npr) ? $line->tva_npr : $line->recuperableonly));
2215
2216 print "</td>";
2217
2218 print '<td class="right"><span class="amount">'.price($line->price)."</span></td>";
2219
2220 print '<td class="right"><span class="amount">'.price($line->price_ttc)."</span></td>";
2221 if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
2222 //print '<td class="right">' . price($line->price_ttc) . "</td>";
2223 print '<td class="right"><span class="amount">'.price($resultarray[2]).'</span></td>';
2224 }
2225
2226 print '<td class="right">'.price($line->price_min).'</td>';
2227 print '<td class="right">'.price($line->price_min_ttc).'</td>';
2228 print '<td class="right">'.$line->price_label.'</td>';
2229
2230 // User
2231 $userstatic = new User($db);
2232 $userstatic->fetch($line->fk_user);
2233 // @TODO Add a cache on $users object
2234 print '<td>';
2235 print $userstatic->getNomUrl(-1, '', 0, 0, 24, 0, 'login');
2236 print '</td>';
2237
2238 // Todo Edit or delete button
2239 // Action
2240 if ($user->hasRight('produit', 'supprimer') || $user->hasRight('service', 'supprimer')) {
2241 print '<td class="right nowraponall">';
2242 print '<a href="'.$_SERVER["PHP_SELF"].'?action=showlog_customer_price&token='.newToken().'&id='.$object->id.'&socid='.$line->fk_soc.'">';
2243 print img_info($langs->trans('PriceByCustomerLog'));
2244 print '</a>';
2245 print ' ';
2246 print '<a class="marginleftonly editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edit_customer_price&token='.newToken().'&id='.$object->id.'&lineid='.$line->id.'">';
2247 print img_edit('default', 0, 'style="vertical-align: middle;"');
2248 print '</a>';
2249 print ' ';
2250 print '<a class="marginleftonly" href="'.$_SERVER["PHP_SELF"].'?action=delete_customer_price&token='.newToken().'&id='.$object->id.'&lineid='.$line->id.'">';
2251 print img_delete('default', 'style="vertical-align: middle;"');
2252 print '</a>';
2253 print '</td>';
2254 }
2255
2256 print "</tr>\n";
2257 }
2258 }
2259
2260 print "</table>";
2261 print '</div>';
2262
2263 print "</form>";
2264 }
2265}
2266
2267// List of price changes - log historic (ordered by descending date)
2268
2269if ((!getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || $action == 'showlog_default_price') && !in_array($action, array('edit_price', 'edit_level_price', 'edit_vat'))) {
2270 $sql = "SELECT p.rowid, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.default_vat_code, p.recuperableonly, p.localtax1_tx, p.localtax1_type, p.localtax2_tx, p.localtax2_type,";
2271 $sql .= " p.price_level, p.price_min, p.price_min_ttc,p.price_by_qty,";
2272 $sql .= " p.date_price as dp, p.fk_price_expression, u.rowid as user_id, u.login";
2273 $sql .= " ,p.price_label";
2274 $sql .= " FROM ".MAIN_DB_PREFIX."product_price as p,";
2275 $sql .= " ".MAIN_DB_PREFIX."user as u";
2276 $sql .= " WHERE fk_product = ".((int) $object->id);
2277 $sql .= " AND p.entity IN (".getEntity('productprice').")";
2278 $sql .= " AND p.fk_user_author = u.rowid";
2279 if (!empty($socid) && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES'))) {
2280 $sql .= " AND p.price_level = ".((int) $soc->price_level);
2281 }
2282 $sql .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC";
2283 // $sql .= $db->plimit();
2284 //print $sql;
2285
2286 $result = $db->query($sql);
2287 if ($result) {
2288 print '<div class="divlogofpreviouscustomerprice">';
2289
2290 $num = $db->num_rows($result);
2291
2292 if (!$num) {
2293 $db->free($result);
2294
2295 // Il doit au moins y avoir la ligne de prix initial.
2296 // On l'ajoute donc pour remettre a niveau (pb vieilles versions)
2297 // We emulate the change of the price from interface with the same value than the one into table llx_product
2298 if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
2299 $ret = $object->updatePrice(($object->multiprices_base_type[1] == 'TTC' ? $object->multiprices_ttc[1] : $object->multiprices[1]), $object->multiprices_base_type[1], $user, (empty($object->multiprices_tva_tx[1]) ? 0 : $object->multiprices_tva_tx[1]), ($object->multiprices_base_type[1] == 'TTC' ? $object->multiprices_min_ttc[1] : $object->multiprices_min[1]), 1);
2300 } else {
2301 $ret = $object->updatePrice(($object->price_base_type == 'TTC' ? $object->price_ttc : $object->price), $object->price_base_type, $user, $object->tva_tx, ($object->price_base_type == 'TTC' ? $object->price_min_ttc : $object->price_min));
2302 }
2303
2304 if ($ret < 0) {
2305 dol_print_error($db, $object->error, $object->errors);
2306 } else {
2307 $result = $db->query($sql);
2308 $num = $db->num_rows($result);
2309 }
2310 }
2311
2312 if ($num > 0) {
2313 // Default prices or
2314 // Log of previous customer prices
2315 $backbutton = '<a class="justalink" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'">'.$langs->trans("Back").'</a>';
2316
2317 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) {
2318 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition, PhanPluginSuspiciousParamOrder
2319 print_barre_liste($langs->trans("DefaultPriceLog"), 0, $_SERVER["PHP_SELF"], '', '', '', $backbutton, 0, $num, 'title_accountancy.png');
2320 } else {
2321 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition, PhanPluginSuspiciousParamOrder
2322 print_barre_liste($langs->trans("PriceByCustomerLog"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, $num, 'title_accountancy.png');
2323 }
2324
2325 print '<!-- List of log prices -->'."\n";
2326 print '<div class="div-table-responsive">'."\n";
2327 print '<table class="liste centpercent">'."\n";
2328
2329 print '<tr class="liste_titre">';
2330 print '<td>'.$langs->trans("AppliedPricesFrom").'</td>';
2331
2332 if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
2333 print '<td class="center">'.$langs->trans("PriceLevel").'</td>';
2334 }
2335 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2336 print '<td class="center">'.$langs->trans("Type").'</td>';
2337 }
2338
2339 print '<td class="center">'.$langs->trans("PriceBase").'</td>';
2340 if (!getDolGlobalString('PRODUIT_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2341 print '<td class="right">'.$langs->trans("DefaultTaxRate").'</td>';
2342 }
2343 print '<td class="right">'.$langs->trans("HT").'</td>';
2344 print '<td class="right">'.$langs->trans("TTC").'</td>';
2345 if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
2346 print '<td class="right">'.$langs->trans("INCT").'</td>';
2347 }
2348 if (!empty($conf->dynamicprices->enabled)) {
2349 print '<td class="right">'.$langs->trans("PriceExpressionSelected").'</td>';
2350 }
2351 print '<td class="right">'.$langs->trans("MinPrice").' '.$langs->trans("HT").'</td>';
2352 print '<td class="right">'.$langs->trans("MinPrice").' '.$langs->trans("TTC").'</td>';
2353 print '<td class="right">'.$langs->trans("Label").'</td>';
2354 print '<td>'.$langs->trans("ChangedBy").'</td>';
2355 if ($user->hasRight('produit', 'supprimer')) {
2356 print '<td class="right">&nbsp;</td>';
2357 }
2358 print '</tr>';
2359
2360 $notfirstlineforlevel = array();
2361
2362 $i = 0;
2363 while ($i < $num) {
2364 $objp = $db->fetch_object($result);
2365
2366 print '<tr class="oddeven">';
2367 // Date
2368 print "<td>".dol_print_date($db->jdate($objp->dp), "dayhour", 'tzuserrel')."</td>";
2369
2370 // Price level
2371 if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
2372 print '<td class="center">'.$objp->price_level."</td>";
2373 }
2374 // Price by quantity
2375 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2376 $type = ($objp->price_by_qty == 1) ? 'PriceByQuantity' : 'Standard';
2377 print '<td class="center">'.$langs->trans($type)."</td>";
2378 }
2379
2380 print '<td class="center">';
2381 if (empty($objp->price_by_qty)) {
2382 print $langs->trans($objp->price_base_type);
2383 }
2384 print "</td>";
2385
2386 if (!getDolGlobalString('PRODUIT_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
2387 print '<td class="right">';
2388
2389 if (empty($objp->price_by_qty)) {
2390 $positiverates = '';
2391 if (price2num($objp->tva_tx)) {
2392 $positiverates .= ($positiverates ? '/' : '').price2num($objp->tva_tx);
2393 }
2394 if (price2num($objp->localtax1_type)) {
2395 $positiverates .= ($positiverates ? '/' : '').price2num($objp->localtax1_tx);
2396 }
2397 if (price2num($objp->localtax2_type)) {
2398 $positiverates .= ($positiverates ? '/' : '').price2num($objp->localtax2_tx);
2399 }
2400 if (empty($positiverates)) {
2401 $positiverates = '0';
2402 }
2403 echo vatrate($positiverates.($objp->default_vat_code ? ' ('.$objp->default_vat_code.')' : ''), true, !empty($objp->tva_npr) ? $objp->tva_npr : 0);
2404 /*
2405 if ($objp->default_vat_code)
2406 {
2407 print vatrate($objp->tva_tx, true) . ' ('.$objp->default_vat_code.')';
2408 }
2409 else print vatrate($objp->tva_tx, true, $objp->recuperableonly);*/
2410 }
2411
2412 print "</td>";
2413 }
2414
2415 // Line for default price
2416 if ($objp->price_base_type == 'HT') {
2417 $pu = $objp->price;
2418 } else {
2419 $pu = $objp->price_ttc;
2420 }
2421
2422 // Local tax was not saved into table llx_product on old version. So we will use value linked to VAT code.
2423 $localtaxarray = getLocalTaxesFromRate($objp->tva_tx.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), 0, $mysoc, $mysoc);
2424 // Define part of HT, VAT, TTC
2425 $resultarray = calcul_price_total(1, $pu, 0, $objp->tva_tx, 1, 1, 0, $objp->price_base_type, $objp->recuperableonly, $object->type, $mysoc, $localtaxarray);
2426 // Calcul du total ht sans remise
2427 $total_ht = $resultarray[0];
2428 $total_vat = $resultarray[1];
2429 $total_localtax1 = $resultarray[9];
2430 $total_localtax2 = $resultarray[10];
2431 $total_ttc = $resultarray[2];
2432
2433 // Price
2434 if (!empty($objp->fk_price_expression) && !empty($conf->dynamicprices->enabled)) {
2435 $price_expression = new PriceExpression($db);
2436 $res = $price_expression->fetch($objp->fk_price_expression);
2437 $title = $price_expression->title;
2438 print '<td class="right"></td>';
2439 print '<td class="right"></td>';
2440 if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
2441 print '<td class="right"></td>';
2442 }
2443 print '<td class="right">'.$title."</td>";
2444 } else {
2445 // Price HT
2446 print '<td class="right">';
2447 if (empty($objp->price_by_qty)) {
2448 print '<span class="amount">'.price($objp->price).'</span>';
2449 }
2450 print "</td>";
2451 // Price TTC
2452 print '<td class="right">';
2453 if (empty($objp->price_by_qty)) {
2454 $price_ttc = $objp->price_ttc;
2455 print '<span class="amount">'.price($price_ttc).'<span>';
2456 }
2457 print "</td>";
2458 if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") {
2459 print '<td class="right">';
2460 print $resultarray[2];
2461 print '</td>';
2462 }
2463 if (!empty($conf->dynamicprices->enabled)) { //Only if module is enabled
2464 print '<td class="right"></td>';
2465 }
2466 }
2467
2468 // Price min
2469 print '<td class="right">';
2470 if (empty($objp->price_by_qty)) {
2471 print price($objp->price_min);
2472 }
2473 print '</td>';
2474
2475 // Price min inc tax
2476 print '<td class="right">';
2477 if (empty($objp->price_by_qty)) {
2478 $price_min_ttc = $objp->price_min_ttc;
2479 print price($price_min_ttc);
2480 }
2481 print '</td>';
2482
2483 // Price Label
2484 print '<td class="right">';
2485 print $objp->price_label;
2486 print '</td>';
2487
2488 // User
2489 print '<td>';
2490 if ($objp->user_id > 0) {
2491 $userstatic = new User($db);
2492 $userstatic->fetch($objp->user_id);
2493 print $userstatic->getNomUrl(-1, '', 0, 0, 24, 0, 'login');
2494 }
2495 print '</td>';
2496
2497
2498 // Action
2499 if ($user->hasRight('produit', 'supprimer')) {
2500 $candelete = 0;
2501 if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
2502 if (empty($notfirstlineforlevel[$objp->price_level])) {
2503 $notfirstlineforlevel[$objp->price_level] = 1;
2504 } else {
2505 $candelete = 1;
2506 }
2507 } elseif ($i > 0) {
2508 $candelete = 1;
2509 }
2510
2511 print '<td class="right">';
2512 if ($candelete || ($db->jdate($objp->dp) >= dol_now())) { // Test on date is to be able to delete a corrupted record with a date in future
2513 print '<a href="'.$_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$object->id.'&lineid='.$objp->rowid.'">';
2514 print img_delete();
2515 print '</a>';
2516 } else {
2517 print '&nbsp;'; // Can not delete last price (it's current price)
2518 }
2519 print '</td>';
2520 }
2521
2522 print "</tr>\n";
2523 $i++;
2524 }
2525
2526 $db->free($result);
2527 print "</table>";
2528 print '</div>';
2529 print "<br>";
2530 }
2531
2532 print '</div>';
2533 } else {
2534 dol_print_error($db);
2535 }
2536}
2537
2538// End of page
2539llxFooter();
2540$db->close();
$id
Definition account.php:39
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:70
Class to manage generation of HTML components Only common components must be here.
Class for accessing price expression table.
Class to parse product price expressions.
File of class to manage predefined price products or services by customer.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
llxFooter()
Footer empty.
Definition document.php:107
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0, $html=0)
Return a string with VAT rate label formatted for view output Used into pdf and HTML pages.
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
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_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
img_info($titlealt='default')
Show info logo.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
calcul_price_total($qty, $pu, $remise_percent_ligne, $txtva, $uselocaltax1_rate, $uselocaltax2_rate, $remise_percent_global, $price_base_type, $info_bits, $type, $seller='', $localtaxes_array=[], $progress=100, $multicurrency_tx=1, $pu_devise=0, $multicurrency_code='')
Calculate totals (net, vat, ...) of a line.
Definition price.lib.php:88
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:137
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.