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