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