* Copyright (C) 2004-2014 Laurent Destailleur * Copyright (C) 2005 Eric Seigne * Copyright (C) 2005-2017 Regis Houssin * Copyright (C) 2006 Andre Cianfarani * Copyright (C) 2014 Florian Henry * Copyright (C) 2014-2018 Juanjo Menent * Copyright (C) 2014-2019 Philippe Grand * Copyright (C) 2014 Ion agorria * Copyright (C) 2015-2023 Alexandre Spangaro * Copyright (C) 2015 Marcos García * Copyright (C) 2016 Ferran Marcet * Copyright (C) 2018-2024 Frédéric France * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2024 MDW * Copyright (C) 2024 Mélina Joum * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/product/price.php * \ingroup product * \brief Page to show product prices */ // Load Dolibarr environment require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_expression.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; $prodcustprice = null; if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { require_once DOL_DOCUMENT_ROOT.'/product/class/productcustomerprice.class.php'; $prodcustprice = new ProductCustomerPrice($db); } /** * @var Conf $conf * @var DoliDB $db * @var HookManager $hookmanager * @var Societe $mysoc * @var Translate $langs * @var User $user */ // Load translation files required by the page $langs->loadLangs(array('products', 'bills', 'companies', 'other')); $error = 0; $errors = array(); $id = GETPOSTINT('id'); $ref = GETPOST('ref', 'alpha'); $action = GETPOST('action', 'aZ09'); $cancel = GETPOST('cancel', 'alpha'); $eid = GETPOSTINT('eid'); $search_soc = GETPOST('search_soc'); // Security check $fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : '')); $fieldtype = (!empty($ref) ? 'ref' : 'rowid'); if ($user->socid) { $socid = $user->socid; } $object = new Product($db); if ($id > 0 || !empty($ref)) { $object->fetch($id, $ref); } $extrafields = new ExtraFields($db); // Clean param if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !getDolGlobalString('PRODUIT_MULTIPRICES_LIMIT')) { $conf->global->PRODUIT_MULTIPRICES_LIMIT = 5; } // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context $hookmanager->initHooks(array('productpricecard', 'globalcard')); if ($object->id > 0) { if ($object->type == $object::TYPE_PRODUCT) { restrictedArea($user, 'produit', $object->id, 'product&product', '', ''); } if ($object->type == $object::TYPE_SERVICE) { restrictedArea($user, 'service', $object->id, 'product&product', '', ''); } } else { restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype); } /* * Actions */ if ($cancel) { $action = ''; } $parameters = array('id' => $id, 'ref' => $ref); $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) { setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); } if (empty($reshook)) { 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 $search_soc = ''; } if ($action == 'setlabelsellingprice' && $user->admin) { require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; $keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.GETPOST('pricelevel'); dolibarr_set_const($db, $keyforlabel, GETPOST('labelsellingprice', 'alpha'), 'chaine', 0, '', $conf->entity); $action = ''; } if (($action == 'update_vat') && !$cancel && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) { $tva_tx_txt = GETPOST('tva_tx', 'alpha'); // tva_tx can be '8.5' or '8.5*' or '8.5 (XXX)' or '8.5* (XXX)' $price_label = GETPOST('price_label', 'alpha'); // We must define tva_tx, npr and local taxes $tva_tx = $tva_tx_txt; $reg = array(); $vatratecode = ''; if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { $vatratecode = $reg[1]; $tva_tx = preg_replace('/\s*\(.*\)/', '', $tva_tx_txt); // Remove code into vatrate. } $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0; $localtax1 = 0; $localtax2 = 0; $localtax1_type = '0'; $localtax2_type = '0'; // If value contains the unique code of vat line (new recommended method), we use it to find npr and local taxes if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { // 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. $vatratecode = $reg[1]; // Get record from code $sql = "SELECT t.rowid, t.type_vat, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code = '".$db->escape($vatratecode)."'"; $sql .= " AND t.type_vat IN (0, 1)"; // Use only VAT rates type all or i.e. the sales type VAT rates. $sql .= " AND t.entity IN (".getEntity('c_tva').")"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } } } else { // Get record with empty code $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code = ''"; $sql .= " AND t.entity IN (".getEntity('c_tva').")"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } } } $object->default_vat_code = $vatratecode; $object->tva_tx = $tva_tx; $object->tva_npr = $npr; $object->localtax1_tx = $localtax1; $object->localtax2_tx = $localtax2; $object->localtax1_type = $localtax1_type; $object->localtax2_type = $localtax2_type; $object->price_label = $price_label; $db->begin(); $resql = $object->update($object->id, $user); if ($resql <= 0) { $error++; setEventMessages($object->error, $object->errors, 'errors'); } if (!$error) { if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); for ($i = 1; $i <= $produit_multiprices_limit; $i++) { // Force the update of the price of the product using the new VAT if ($object->multiprices_base_type[$i] == 'HT') { $oldprice = $object->multiprices[$i]; $oldminprice = $object->multiprices_min[$i]; } else { $oldprice = $object->multiprices_ttc[$i]; $oldminprice = $object->multiprices_min_ttc[$i]; } $oldpricebasetype = $object->multiprices_base_type[$i]; $oldnpr = $object->multiprices_recuperableonly[$i]; //$localtaxarray=array('0'=>$localtax1_type,'1'=>$localtax1,'2'=>$localtax2_type,'3'=>$localtax2); $localtaxarray = array(); // We do not store localtaxes into product, we will use instead the "vat code" to retrieve them. $level = $i; $ret = $object->updatePrice($oldprice, $oldpricebasetype, $user, $tva_tx, $oldminprice, $level, $oldnpr, 0, 0, $localtaxarray, $vatratecode, $price_label); if ($ret < 0) { $error++; setEventMessages($object->error, $object->errors, 'errors'); } } } else { // Force the update of the price of the product using the new VAT if ($object->price_base_type == 'HT') { $oldprice = $object->price; $oldminprice = $object->price_min; } else { $oldprice = $object->price_ttc; $oldminprice = $object->price_min_ttc; } $oldpricebasetype = $object->price_base_type; $oldnpr = $object->tva_npr; //$localtaxarray=array('0'=>$localtax1_type,'1'=>$localtax1,'2'=>$localtax2_type,'3'=>$localtax2); $localtaxarray = array(); // We do not store localtaxes into product, we will use instead the "vat code" to retrieve them when required. $level = 0; $ret = $object->updatePrice($oldprice, $oldpricebasetype, $user, $tva_tx, $oldminprice, $level, $oldnpr, 0, 0, $localtaxarray, $vatratecode, $price_label); if ($ret < 0) { $error++; setEventMessages($object->error, $object->errors, 'errors'); } } } if (!$error) { $db->commit(); } else { $db->rollback(); } $action = ''; } if (($action == 'update_price' || $action == 'update_level_price') && !$cancel && $object->getRights()->creer) { $error = 0; $pricestoupdate = array(); $psq = GETPOST('psqflag'); $psq = empty($newpsq) ? 0 : $newpsq; $maxpricesupplier = $object->min_recommended_price(); if (isModEnabled('dynamicprices')) { $object->fk_price_expression = empty($eid) ? 0 : $eid; //0 discards expression if ($object->fk_price_expression != 0) { //Check the expression validity by parsing it require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_parser.class.php'; $priceparser = new PriceParser($db); if ($priceparser->parseProduct($object) < 0) { $error++; setEventMessages($priceparser->translatedError(), null, 'errors'); } } } // Multiprices if (!$error && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || ($action == 'update_level_price' && getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')))) { $newprice = GETPOST('price', 'array'); $newprice_min = GETPOST('price_min', 'array'); $newpricebase = GETPOST('multiprices_base_type', 'array'); $newvattx = GETPOST('tva_tx', 'array'); $newvatnpr = GETPOST('tva_npr', 'array'); $newlocaltax1_tx = GETPOST('localtax1_tx', 'array'); $newlocaltax1_type = GETPOST('localtax1_type', 'array'); $newlocaltax2_tx = GETPOST('localtax2_tx', 'array'); $newlocaltax2_type = GETPOST('localtax2_type', 'array'); //Shall we generate prices using price rules? $object->price_autogen = (int) (GETPOST('usePriceRules') == 'on'); $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); for ($i = 1; $i <= $produit_multiprices_limit; $i++) { if (!isset($newprice[$i])) { continue; } $tva_tx_txt = $newvattx[$i]; $tva_tx = $tva_tx_txt; $vatratecode = ''; $reg = array(); if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { $vat_src_code = $reg[1]; $tva_tx = preg_replace('/\s*\(.*\)/', '', $tva_tx_txt); // Remove code into vatrate. } $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0; $localtax1 = $newlocaltax1_tx[$i]; $localtax1_type = $newlocaltax1_type[$i]; $localtax2 = $newlocaltax2_tx[$i]; $localtax2_type = $newlocaltax2_type[$i]; if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { // We look into database using code $vatratecode = $reg[1]; // Get record from code $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code ='".$db->escape($vatratecode)."'"; $sql .= " AND t.entity IN (".getEntity('c_tva').")"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule. if (in_array($mysoc->country_code, array('ES'))) { $localtax1 = get_localtax($tva_tx, 1); $localtax2 = get_localtax($tva_tx, 2); } } } else { // Get record with empty code $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code = ''"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } } } $pricestoupdate[$i] = array( 'price' => price2num($newprice[$i], '', 2), 'price_min' => price2num($newprice_min[$i], '', 2), 'price_base_type' => $newpricebase[$i], 'default_vat_code' => $vatratecode, 'vat_tx' => $tva_tx, // default_vat_code should be used in priority in a future 'npr' => $npr, // default_vat_code should be used in priority in a future 'localtaxes_array' => array('0' => $localtax1_type, '1' => $localtax1, '2' => $localtax2_type, '3' => $localtax2) // default_vat_code should be used in priority in a future ); //If autogeneration is enabled, then we only set the first level if ($object->price_autogen) { break; } } } elseif (!$error) { $newprice = price2num(GETPOST('price', 'alpha'), '', 2); $newprice_min = price2num(GETPOST('price_min', 'alpha'), '', 2); $newpricebase = GETPOST('price_base_type', 'alpha'); $tva_tx_txt = GETPOST('tva_tx', 'alpha'); // tva_tx can be '8.5' or '8.5*' or '8.5 (XXX)' or '8.5* (XXX)' $price_label = GETPOST('price_label', 'alpha'); $tva_tx = $tva_tx_txt; $vatratecode = ''; $reg = array(); if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { $vat_src_code = $reg[1]; $tva_tx = preg_replace('/\s*\(.*\)/', '', $tva_tx_txt); // Remove code into vatrate. } $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0; $localtax1 = 0; $localtax2 = 0; $localtax1_type = '0'; $localtax2_type = '0'; // If value contains the unique code of vat line (new recommended method), we use it to find npr and local taxes if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { // We look into database using code $vatratecode = $reg[1]; // Get record from code $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code ='".$db->escape($vatratecode)."'"; $sql .= " AND t.entity IN (".getEntity('c_tva').")"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule. if (in_array($mysoc->country_code, array('ES'))) { $localtax1 = get_localtax($tva_tx, 1); $localtax2 = get_localtax($tva_tx, 2); } } } else { // Get record with empty code $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code = ''"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } } } $pricestoupdate[0] = array( 'price' => $newprice, 'price_label' => $price_label, 'price_min' => $newprice_min, 'price_base_type' => $newpricebase, 'default_vat_code' => $vatratecode, 'vat_tx' => $tva_tx, // default_vat_code should be used in priority in a future 'npr' => $npr, // default_vat_code should be used in priority in a future 'localtaxes_array' => array('0' => $localtax1_type, '1' => $localtax1, '2' => $localtax2_type, '3' => $localtax2) // default_vat_code should be used in priority in a future ); } if (!$error) { $db->begin(); foreach ($pricestoupdate as $key => $val) { $newprice = $val['price']; if ($val['price'] < $val['price_min'] && !empty($object->fk_price_expression)) { $newprice = $val['price_min']; //Set price same as min, the user will not see the } $newprice = price2num($newprice, 'MU'); $newprice_min = price2num($val['price_min'], 'MU'); $newvattx = price2num($val['vat_tx']); if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE') && $newprice_min < $maxpricesupplier) { setEventMessages($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, - 1, - 1, 'auto')), null, 'errors'); $error++; break; } // If price has changed, we update it 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) { $res = $object->updatePrice($newprice, $val['price_base_type'], $user, $val['vat_tx'], $newprice_min, $key, $val['npr'], $psq, 0, $val['localtaxes_array'], $val['default_vat_code'], $val['price_label']); } else { $res = 0; } if ($res < 0) { $error++; setEventMessages($object->error, $object->errors, 'errors'); break; } // Update level price extrafields $price_extralabels = $extrafields->fetch_name_optionals_label("product_price"); if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && !empty($price_extralabels)) { $sql = "SELECT rowid"; $sql .= " FROM ".$object->db->prefix()."product_price"; $sql .= " WHERE entity IN (".getEntity('productprice').")"; $sql .= " AND price_level=".((int) $key); // $i $sql .= " AND fk_product = ".((int) $object->id); $sql .= " ORDER BY date_price DESC, rowid DESC"; $sql .= " LIMIT 1"; $resql = $object->db->query($sql); if ($resql) { $lineid = $object->db->fetch_object($resql); $db->free($resql); } if (!empty($lineid->rowid)) { foreach ($price_extralabels as $code => $label) { $code_array = GETPOST($code, 'array'); $object->array_options['options_'.$code] = $code_array[$key]; } // We need to force table to update product_price and not product extrafields $object->id = $lineid->rowid; $object->table_element = 'product_price'; $result = $object->insertExtraFields(); // Back to product table $object->id = $id; $object->table_element = 'product'; if ($result < 0) { $error++; } } } } } if (!$error && $object->update($object->id, $user) < 0) { $error++; setEventMessages($object->error, $object->errors, 'errors'); } if (empty($error)) { $action = ''; setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); $db->commit(); } else { $action = 'edit_price'; $db->rollback(); } } if ($action == 'delete' && $user->hasRight('produit', 'supprimer')) { $result = $object->log_price_delete($user, GETPOSTINT('lineid')); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); } } // Set Price by quantity if ($action == 'activate_price_by_qty') { // Activating product price by quantity add a new price line with price_by_qty set to 1 $level = GETPOSTINT('level'); $basePrice = ($object->price_base_type == 'HT') ? $object->price : $object->price_ttc; $basePriceMin = ($object->price_base_type == 'HT') ? $object->price_min : $object->price_min_ttc; $ret = $object->updatePrice($basePrice, $object->price_base_type, $user, $object->tva_tx, $basePriceMin, $level, $object->tva_npr, 1); if ($ret < 0) { setEventMessages($object->error, $object->errors, 'errors'); } } // Unset Price by quantity if ($action == 'disable_price_by_qty') { // Disabling product price by quantity add a new price line with price_by_qty set to 0 $level = GETPOSTINT('level'); $basePrice = ($object->price_base_type == 'HT') ? $object->price : $object->price_ttc; $basePriceMin = ($object->price_base_type == 'HT') ? $object->price_min : $object->price_min_ttc; $ret = $object->updatePrice($basePrice, $object->price_base_type, $user, $object->tva_tx, $basePriceMin, $level, $object->tva_npr, 0); if ($ret < 0) { setEventMessages($object->error, $object->errors, 'errors'); } } if ($action == 'edit_price_by_qty') { // Edition d'un prix par quantité $rowid = GETPOSTINT('rowid'); } // Add or update price by quantity if ($action == 'update_price_by_qty') { // Récupération des variables $rowid = GETPOSTINT('rowid'); $priceid = GETPOSTINT('priceid'); $newprice = price2num(GETPOST("price"), 'MU', 2); // $newminprice=price2num(GETPOST("price_min"),'MU'); // TODO : Add min price management $quantity = price2num(GETPOST('quantity'), 'MS', 2); $remise_percent = price2num(GETPOST('remise_percent'), '', 2); $remise = 0; // TODO : allow discount by amount when available on documents if (empty($quantity)) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Qty")), null, 'errors'); } if (empty($newprice)) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Price")), null, 'errors'); } if (!$error) { // Calcul du prix HT et du prix unitaire if ($object->price_base_type == 'TTC') { $price = (float) price2num($newprice) / (1 + ($object->tva_tx / 100)); } $price = price2num($newprice, 'MU'); $unitPrice = price2num((float) $price / (float) $quantity, 'MU'); // Ajout / mise à jour if ($rowid > 0) { $sql = "UPDATE ".MAIN_DB_PREFIX."product_price_by_qty SET"; $sql .= " price=".((float) $price).","; $sql .= " unitprice=".((float) $unitPrice).","; $sql .= " quantity=".((float) $quantity).","; $sql .= " remise_percent=".((float) $remise_percent).","; $sql .= " remise=".((float) $remise); $sql .= " WHERE rowid = ".((int) $rowid); $result = $db->query($sql); if (!$result) { dol_print_error($db); } } else { $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price_by_qty (fk_product_price,price,unitprice,quantity,remise_percent,remise) values ("; $sql .= ((int) $priceid).','.((float) $price).','.((float) $unitPrice).','.((float) $quantity).','.((float) $remise_percent).','.((float) $remise).')'; $result = $db->query($sql); if (!$result) { if ($db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') { setEventMessages($langs->trans("DuplicateRecord"), null, 'errors'); } else { dol_print_error($db); } } } } } if ($action == 'delete_price_by_qty') { $rowid = GETPOSTINT('rowid'); if (!empty($rowid)) { $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price_by_qty"; $sql .= " WHERE rowid = ".((int) $rowid); $result = $db->query($sql); } else { setEventMessages(('delete_price_by_qty'.$langs->transnoentities('MissingIds')), null, 'errors'); } } if ($action == 'delete_all_price_by_qty') { $priceid = GETPOSTINT('priceid'); if (!empty($rowid)) { $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price_by_qty"; $sql .= " WHERE fk_product_price = ".((int) $priceid); $result = $db->query($sql); } else { setEventMessages(('delete_price_by_qty'.$langs->transnoentities('MissingIds')), null, 'errors'); } } /** * *************************************************** * Price by customer * **************************************************** */ if ($action == 'add_customer_price_confirm' && !$cancel && $prodcustprice !== null && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) { $maxpricesupplier = $object->min_recommended_price(); $update_child_soc = GETPOSTINT('updatechildprice'); // add price by customer $prodcustprice->fk_soc = GETPOSTINT('socid'); $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha'); $prodcustprice->fk_product = $object->id; $prodcustprice->price = price2num(GETPOST("price"), 'MU'); $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU'); $prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha'); $prodcustprice->price_label = GETPOST("price_label", 'alpha'); $extralabels = $extrafields->fetch_name_optionals_label("product_customer_price"); $extrafield_values = $extrafields->getOptionalsFromPost("product_customer_price"); $tva_tx_txt = GETPOST("tva_tx", 'alpha'); $tva_tx = $tva_tx_txt; $vatratecode = ''; if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { $vat_src_code = $reg[1]; $tva_tx = preg_replace('/\s*\(.*\)/', '', $tva_tx_txt); // Remove code into vatrate. } $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0; $localtax1 = 0; $localtax2 = 0; $localtax1_type = '0'; $localtax2_type = '0'; // If value contains the unique code of vat line (new recommended method), we use it to find npr and local taxes if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { // We look into database using code $vatratecode = $reg[1]; // Get record from code $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code ='".$db->escape($vatratecode)."'"; $sql .= " AND t.entity IN (".getEntity('c_tva').")"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule. if (in_array($mysoc->country_code, array('ES'))) { $localtax1 = get_localtax($tva_tx, 1); $localtax2 = get_localtax($tva_tx, 2); } } } else { // Get record with empty code $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code = ''"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } } } $prodcustprice->default_vat_code = $vatratecode; $prodcustprice->tva_tx = $tva_tx; $prodcustprice->recuperableonly = $npr; $prodcustprice->localtax1_tx = $localtax1; $prodcustprice->localtax2_tx = $localtax2; $prodcustprice->localtax1_type = $localtax1_type; $prodcustprice->localtax2_type = $localtax2_type; if (!($prodcustprice->fk_soc > 0)) { $langs->load("errors"); setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ThirdParty")), null, 'errors'); $error++; $action = 'add_customer_price'; } if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE') && $prodcustprice->price_min < $maxpricesupplier) { $langs->load("errors"); setEventMessages($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')), null, 'errors'); $error++; $action = 'add_customer_price'; } if (!$error) { $result = $prodcustprice->create($user, 0, $update_child_soc); if ($result > 0) { if (!empty($extrafield_values) && is_array($extrafield_values)) { $productcustomerprice = new ProductCustomerPrice($db); $res = $productcustomerprice->fetch($prodcustprice->id); if ($res > 0) { foreach ($extrafield_values as $key => $value) { $productcustomerprice->array_options[$key] = $value; } $result2 = $productcustomerprice->insertExtraFields(); if ($result2 < 0) { $prodcustprice->error = $productcustomerprice->error; $prodcustprice->errors = $productcustomerprice->errors; $error++; } } } } if ($result < 0) { setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors'); } else { setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); } $action = ''; } } if ($action == 'delete_customer_price' && $prodcustprice !== null && ($user->hasRight('produit', 'supprimer') || $user->hasRight('service', 'supprimer'))) { // Delete price by customer $prodcustprice->id = GETPOSTINT('lineid'); $result = $prodcustprice->delete($user); if ($result > 0) { $db->query("DELETE FROM ".MAIN_DB_PREFIX."product_customer_price_extrafields WHERE fk_object = ".((int) $prodcustprice->id)); setEventMessages($langs->trans("PriceRemoved"), null, 'mesgs'); } else { $error++; setEventMessages($object->error, $object->errors, 'errors'); } if ($result < 0) { setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors'); } else { setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs'); } $action = ''; } if ($action == 'update_customer_price_confirm' && !$cancel && $prodcustprice !== null && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) { $maxpricesupplier = $object->min_recommended_price(); $update_child_soc = GETPOSTINT('updatechildprice'); $prodcustprice->fetch(GETPOSTINT('lineid')); // update price by customer $prodcustprice->ref_customer = GETPOST('ref_customer', 'alpha'); $prodcustprice->price = price2num(GETPOST("price"), 'MU'); $prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU'); $prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha'); $prodcustprice->price_label = GETPOST("price_label", 'alpha'); $extralabels = $extrafields->fetch_name_optionals_label("product_customer_price"); $extrafield_values = $extrafields->getOptionalsFromPost("product_customer_price"); $tva_tx_txt = GETPOST("tva_tx"); $tva_tx = $tva_tx_txt; $vatratecode = ''; if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { $vat_src_code = $reg[1]; $tva_tx = preg_replace('/\s*\(.*\)/', '', $tva_tx_txt); // Remove code into vatrate. } $tva_tx = price2num(preg_replace('/\*/', '', $tva_tx)); // keep remove all after the numbers and dot $npr = preg_match('/\*/', $tva_tx_txt) ? 1 : 0; $localtax1 = 0; $localtax2 = 0; $localtax1_type = '0'; $localtax2_type = '0'; // If value contains the unique code of vat line (new recommended method), we use it to find npr and local taxes if (preg_match('/\((.*)\)/', $tva_tx_txt, $reg)) { // We look into database using code $vatratecode = $reg[1]; // Get record from code $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code ='".$db->escape($vatratecode)."'"; $sql .= " AND t.entity IN (".getEntity('c_tva').")"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } // If spain, we don't use the localtax found into tax record in database with same code, but using the get_localtax rule. if (in_array($mysoc->country_code, array('ES'))) { $localtax1 = get_localtax($tva_tx, 1); $localtax2 = get_localtax($tva_tx, 2); } } } else { // Get record with empty code $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type"; $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c"; $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'"; $sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1"; $sql .= " AND t.code = ''"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $npr = $obj->recuperableonly; $localtax1 = $obj->localtax1; $localtax2 = $obj->localtax2; $localtax1_type = $obj->localtax1_type; $localtax2_type = $obj->localtax2_type; } } } $prodcustprice->default_vat_code = $vatratecode; $prodcustprice->tva_tx = $tva_tx; $prodcustprice->recuperableonly = $npr; $prodcustprice->localtax1_tx = $localtax1; $prodcustprice->localtax2_tx = $localtax2; $prodcustprice->localtax1_type = $localtax1_type; $prodcustprice->localtax2_type = $localtax2_type; if ($prodcustprice->price_min < $maxpricesupplier && getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) { setEventMessages($langs->trans("MinimumPriceLimit", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')), null, 'errors'); $error++; $action = 'update_customer_price'; } if (!$error) { $result = $prodcustprice->update($user, 0, $update_child_soc); if ($result > 0) { if (!empty($extrafield_values) && is_array($extrafield_values)) { $productcustomerprice = new ProductCustomerPrice($db); $res = $productcustomerprice->fetch($prodcustprice->id); if ($res > 0) { foreach ($extrafield_values as $key => $value) { $productcustomerprice->array_options[$key] = $value; } $result2 = $productcustomerprice->insertExtraFields(); if ($result2 < 0) { $prodcustprice->error = $productcustomerprice->error; $prodcustprice->errors = $productcustomerprice->errors; $error++; } } } } if ($result < 0) { setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors'); } else { setEventMessages($langs->trans("Save"), null, 'mesgs'); } $action = ''; } } } /* * View */ $form = new Form($db); if (!empty($id) || !empty($ref)) { // fetch updated prices $object->fetch($id, $ref); } $title = $langs->trans('ProductServiceCard'); $helpurl = ''; $shortlabel = dol_trunc($object->label, 16); if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) { $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('SellingPrices'); $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:Módulo_Productos'; } if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) { $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('SellingPrices'); $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:Módulo_Servicios'; } llxHeader('', $title, $helpurl, '', 0, 0, '', '', '', 'classforhorizontalscrolloftabs mod-product page-price'); $head = product_prepare_head($object); $titre = $langs->trans("CardProduct".$object->type); $picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product'); print dol_get_fiche_head($head, 'price', $titre, -1, $picto); $linkback = ''.$langs->trans("BackToList").''; $object->next_prev_filter = "(te.fk_product_type:=:".((int) $object->type).")"; $shownav = 1; if ($user->socid && !in_array('product', explode(',', getDolGlobalString('MAIN_MODULES_FOR_EXTERNAL')))) { $shownav = 0; } dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref'); print '
'; print '
'; print ''; // Price per customer segment/level if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { $soc = null; // Price and min price are variable (depends on level of company). if (!empty($socid)) { $soc = new Societe($db); $soc->id = $socid; $soc->fetch($socid); // Type if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print ''; } // Selling price print ''; print ''; // Price min print ''; if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility // TVA print ''; } else { // TVA print ''; } } else { if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility // Type if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print ''; } // We show only vat for level 1 print ''; print ''; print ''; } else { // Type if (isModEnabled("product") && isModEnabled("service")) { $typeformat = 'select;0:'.$langs->trans("Product").',1:'.$langs->trans("Service"); print ''; } // TVA print ''; print ''; } print '
'; print (!getDolGlobalString('PRODUCT_DENY_CHANGE_PRODUCT_TYPE')) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); print ''; print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat); print '
'; print $langs->trans("SellingPrice"); print ''; if ($object->multiprices_base_type[$soc->price_level] == 'TTC') { print ''.price($object->multiprices_ttc[$soc->price_level]).''; } else { print ''.price($object->multiprices[$soc->price_level]).''; } if ($object->multiprices_base_type[$soc->price_level]) { print ' '.$langs->trans($object->multiprices_base_type[$soc->price_level]); } else { print ' '.$langs->trans($object->price_base_type); } print '
'.$langs->trans("MinPrice").''; if ($object->multiprices_base_type[$soc->price_level] == 'TTC') { print price($object->multiprices_min_ttc[$soc->price_level]).' '.$langs->trans($object->multiprices_base_type[$soc->price_level]); } else { 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]); } print '
'.$langs->trans("DefaultTaxRate").''; $positiverates = ''; if (price2num($object->multiprices_tva_tx[$soc->price_level])) { $positiverates .= ($positiverates ? '/' : '').price2num($object->multiprices_tva_tx[$soc->price_level]); } if (price2num($object->multiprices_localtax1_type[$soc->price_level])) { $positiverates .= ($positiverates ? '/' : '').price2num($object->multiprices_localtax1_tx[$soc->price_level]); } if (price2num($object->multiprices_localtax2_type[$soc->price_level])) { $positiverates .= ($positiverates ? '/' : '').price2num($object->multiprices_localtax2_tx[$soc->price_level]); } if (empty($positiverates)) { $positiverates = '0'; } echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr); //print vatrate($object->multiprices_tva_tx[$soc->price_level], true); print '
'.$langs->trans("DefaultTaxRate").''; $positiverates = ''; if (price2num($object->tva_tx)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->tva_tx); } if (price2num($object->localtax1_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax1_tx); } if (price2num($object->localtax2_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax2_tx); } if (empty($positiverates)) { $positiverates = '0'; } echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr); /* if ($object->default_vat_code) { print vatrate($object->tva_tx, true) . ' ('.$object->default_vat_code.')'; } else print vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true);*/ print '
'; print (!getDolGlobalString('PRODUCT_DENY_CHANGE_PRODUCT_TYPE')) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); print ''; print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat); print '
'.$langs->trans("DefaultTaxRate").''.vatrate($object->multiprices_tva_tx[1], true).'
'; print (!getDolGlobalString('PRODUCT_DENY_CHANGE_PRODUCT_TYPE')) ? $form->editfieldkey("Type", 'fk_product_type', $object->type, $object, 0, $typeformat) : $langs->trans('Type'); print ''; print $form->editfieldval("Type", 'fk_product_type', $object->type, $object, 0, $typeformat); print '
'.$langs->trans("DefaultTaxRate").''; // TODO We show localtax from $object, but this properties may not be correct. Only value $object->default_vat_code is guaranteed. $positiverates = ''; if (price2num($object->tva_tx)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->tva_tx); } if (price2num($object->localtax1_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax1_tx); } if (price2num($object->localtax2_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax2_tx); } if (empty($positiverates)) { $positiverates = '0'; } print vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr, 1); /* if ($object->default_vat_code) { print vatrate($object->tva_tx, true) . ' ('.$object->default_vat_code.')'; } else print vatrate($object->tva_tx . ($object->tva_npr ? '*' : ''), true);*/ print '
'; print '
'; print ''; print ''; print ''; print ''; // fetch optionals attributes and labels $extrafields->fetch_name_optionals_label("product_price"); if ($extrafields->attributes["product_price"] && array_key_exists('label', $extrafields->attributes["product_price"])) { $extralabels = $extrafields->attributes["product_price"]['label']; if (!empty($extralabels)) { foreach ($extralabels as $key => $value) { // Show field if not hidden if (!empty($extrafields->attributes["product_price"]['list'][$key]) && $extrafields->attributes["product_price"]['list'][$key] != 3) { if (!empty($extrafields->attributes["product_price"]['langfile'][$key])) { $langs->load($extrafields->attributes["product_price"]['langfile'][$key]); } if (!empty($extrafields->attributes["product_price"]['help'][$key])) { $extratitle = $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_price"]['help'][$key])); } else { $extratitle = $langs->trans($value); } $field = 'ef.' . $key; print ''; } } } } print ''; $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); for ($i = 1; $i <= $produit_multiprices_limit; $i++) { print ''; // Label of price print ''; if ($object->multiprices_base_type [$i] == 'TTC') { print ''; } else { print ' '.$langs->trans($object->price_base_type).''; } // Prix min print ''; if (!empty($extralabels)) { $sql1 = "SELECT rowid"; $sql1 .= " FROM ".$object->db->prefix()."product_price"; $sql1 .= " WHERE entity IN (".getEntity('productprice').")"; $sql1 .= " AND price_level=".((int) $i); $sql1 .= " AND fk_product = ".((int) $object->id); $sql1 .= " ORDER BY date_price DESC, rowid DESC"; $sql1 .= " LIMIT 1"; $resql1 = $object->db->query($sql1); if ($resql1) { $lineid = $object->db->fetch_object($resql1); } $sql2 = "SELECT"; $sql2 .= " fk_object"; foreach ($extralabels as $key => $value) { $sql2 .= ", ".$key; } $sql2 .= " FROM ".MAIN_DB_PREFIX."product_price_extrafields"; $sql2 .= " WHERE fk_object = ".((int) $lineid->rowid); $resql2 = $db->query($sql2); if ($resql2) { if ($db->num_rows($resql2) != 1) { foreach ($extralabels as $key => $value) { if (!empty($extrafields->attributes["product_price"]['list'][$key]) && $extrafields->attributes["product_price"]['list'][$key] != 3) { print ''; } } } else { $obj = $db->fetch_object($resql2); foreach ($extralabels as $key => $value) { if (!empty($extrafields->attributes["product_price"]['list'][$key]) && $extrafields->attributes["product_price"]['list'][$key] != 3) { print '"; } } } $db->free($resql1); $db->free($resql2); } } print ''; // Price by quantity 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 print ''; } } } } else { // TVA print ''; // Price print ''; // Price minimum print ''; // Price Label print ''; // Price by quantity if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { // TODO Fix the form inside tr instead of td print ''; } } print "
'; print $langs->trans("PriceLevel"); if ($user->admin) { print ' id.'">'.img_edit($langs->trans('EditSellingPriceLabel'), 0).''; } print ''.$langs->trans("SellingPrice").''.$langs->trans("MinPrice").''.$extratitle.'
'; $keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.$i; if (preg_match('/editlabelsellingprice/', $action)) { print '
'; print ''; print ''; print ''; print $langs->trans("SellingPrice").' '.$i.' - '; print ''; print ' '; print '
'; } else { print $langs->trans("SellingPrice").' '.$i; if (getDolGlobalString($keyforlabel)) { print ' - '.$langs->trans(getDolGlobalString($keyforlabel)); } } print '
'.price($object->multiprices_ttc[$i]); } else { print ''.price($object->multiprices[$i]); } if ($object->multiprices_base_type[$i]) { print ' '.$langs->trans($object->multiprices_base_type [$i]).''; if (empty($object->multiprices_base_type[$i])) { $object->multiprices_base_type[$i] = "HT"; } if ($object->multiprices_base_type[$i] == 'TTC') { print price($object->multiprices_min_ttc[$i]).' '.$langs->trans($object->multiprices_base_type[$i]); } else { print price($object->multiprices_min[$i]).' '.$langs->trans($object->multiprices_base_type[$i]); } print ''.$extrafields->showOutputField($key, $obj->{$key}, '', 'product_price')."
'.$langs->trans("PriceByQuantity").' '.$i; if (getDolGlobalString($keyforlabel)) { print ' - '.$langs->trans(getDolGlobalString($keyforlabel)); } print ''; if ($object->prices_by_qty[$i] == 1) { print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; foreach ($object->prices_by_qty_list[$i] as $ii => $prices) { if ($action == 'edit_price_by_qty' && $rowid == $prices['rowid'] && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) { print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; } else { print ''; print ''; print ''; print ''; print ''; print ''; print ''; } } if ($action != 'edit_price_by_qty' && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) { print ''; print ''; print ''; print ''; // id in product_price print ''; // id in product_price print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; } print '
'.$langs->trans("PriceByQuantityRange").' '.$i.''.$langs->trans("HT").''.$langs->trans("UnitPrice").''.$langs->trans("Discount").' 
 '.$object->price_base_type.' %
'.$prices['quantity'].''.price($prices['price']).''.price($prices['unitprice']).''.price($prices['remise_percent']).' %'; if (($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) { print ''; print img_edit().''; print ''; print img_delete().''; } else { print ' '; } print '
 '.$object->price_base_type.'  %
'; print '('.$langs->trans("DisablePriceByQty").')'; } else { print $langs->trans("No"); print '  ('.$langs->trans("Activate").')'; } print '
'.$langs->trans("DefaultTaxRate").''; $positiverates = ''; if (price2num($object->tva_tx)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->tva_tx); } if (price2num($object->localtax1_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax1_tx); } if (price2num($object->localtax2_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax2_tx); } if (empty($positiverates)) { $positiverates = '0'; } echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr, 0, 1); /* if ($object->default_vat_code) { print vatrate($object->tva_tx, true) . ' ('.$object->default_vat_code.')'; } else print vatrate($object->tva_tx, true, $object->tva_npr, true);*/ print '
'.$langs->trans("SellingPrice").''; if ($object->price_base_type == 'TTC') { print price($object->price_ttc).' '.$langs->trans($object->price_base_type); } else { print price($object->price).' '.$langs->trans($object->price_base_type); if (getDolGlobalString('PRODUCT_DISPLAY_VAT_INCL_PRICES') && !empty($object->price_ttc)) { print ' - ' . price($object->price_ttc).' '.$langs->trans('TTC') . ''; } } print '
'.$langs->trans("MinPrice").''; if ($object->price_base_type == 'TTC') { print price($object->price_min_ttc).' '.$langs->trans($object->price_base_type); } else { print price($object->price_min).' '.$langs->trans($object->price_base_type); if (getDolGlobalString('PRODUCT_DISPLAY_VAT_INCL_PRICES') && !empty($object->price_min_ttc)) { print ' - ' . price($object->price_min_ttc).' '.$langs->trans('TTC') . ''; } } print '
'.$langs->trans("PriceLabel").''; print $object->price_label; print '
'.$langs->trans("PriceByQuantity"); if ($object->prices_by_qty[0] == 0) { print '  ('.$langs->trans("Activate").')'; } else { print '  ('.$langs->trans("DisablePriceByQty").')'; } print ''; if ($object->prices_by_qty[0] == 1) { print ''; print ''; //print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; if ($action != 'edit_price_by_qty') { print ''; // FIXME a form into a table is not allowed print ''; print ''; print ''; // id in product_price print ''; // id in product_price_by_qty print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; } foreach ($object->prices_by_qty_list[0] as $ii => $prices) { if ($action == 'edit_price_by_qty' && $rowid == $prices['rowid'] && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) { print ''; print ''; print ''; print ''; // id in product_price print ''; // id in product_price_by_qty print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; } else { print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; } } print '
' . $langs->trans("PriceByQuantityRange") . ''.$langs->trans("Quantity").''.$langs->trans("Price").''.$langs->trans("UnitPrice").''.$langs->trans("Discount").' 
'; //print $object->price_base_type; print '  %
'; //print $object->price_base_type; print $prices['price_base_type']; print '  %
'.$prices['quantity'].''.price($prices['price']).''; //print $object->price_base_type; print $prices['price_base_type']; print ''.price($prices['unitprice']).''.price($prices['remise_percent']).' %'; if (($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) { print ''; print img_edit().''; print ''; print img_delete().''; } else { print ' '; } print '
'; } else { print $langs->trans("No"); } print '
\n"; print '
'; print '
'; print dol_get_fiche_end(); /* * Action bar */ if (!$action || $action == 'delete' || $action == 'showlog_customer_price' || $action == 'showlog_default_price' || $action == 'add_customer_price' || $action == 'activate_price_by_qty' || $action == 'disable_price_by_qty') { print "\n".'
'."\n"; $parameters = array(); $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been if (empty($reshook)) { if ($object->isVariant()) { if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) { print ''; } } else { if (!getDolGlobalString('PRODUIT_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) { print ''; } else { print '
' . $langs->trans("UpdateDefaultPrice") . '
'; } } if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) { print ''; } else { print '
' . $langs->trans("AddCustomerPrice") . '
'; } } if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) { print ''; } else { print '
' . $langs->trans("UpdateVAT") . '
'; } if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) { print ''; } else { print '
' . $langs->trans("UpdateLevelPrices") . '
'; } } } } print "\n
\n"; } /* * Edit price area */ if ($action == 'edit_vat' && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) { print load_fiche_titre($langs->trans("UpdateVAT"), ''); print '
'; print ''; print ''; print ''; print dol_get_fiche_head(); print ''; // VAT print ''; print '
'.$langs->trans("DefaultTaxRate").''; print $form->load_tva("tva_tx", $object->default_vat_code ? $object->tva_tx.' ('.$object->default_vat_code.')' : $object->tva_tx, $mysoc, null, $object->id, $object->tva_npr, $object->type, false, 1); print '
'; print dol_get_fiche_end(); print $form->buttonsSaveCancel(); print '

'; } if (($action == 'edit_price' || $action == 'edit_level_price') && $object->getRights()->creer) { print '
'; print load_fiche_titre($langs->trans("NewPrice"), ''); if (!getDolGlobalString('PRODUIT_MULTIPRICES') && $action != 'edit_level_price') { print ''."\n"; print '
'; print ''; print ''; print ''; print dol_get_fiche_head(); print '
'; print ''; // VAT print ''; // Price base print ''; print ''; print ''; // Only show price mode and expression selector if module is enabled if (isModEnabled('dynamicprices')) { // Price mode selector print ''."\n"; print ''; // This code hides the numeric price input if is not selected, loads the editor page if editor button is pressed ?> fetch($id, $ref, '', 1); //Ignore the math expression when getting the price print ''; // Price minimum print ''; } print ''; print ''; // Price Label print ''; print ''; $parameters = array(); $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook print '
'.$langs->trans("DefaultTaxRate").''; print $form->load_tva("tva_tx", $object->default_vat_code ? $object->tva_tx.' ('.$object->default_vat_code.')' : $object->tva_tx, $mysoc, null, $object->id, $object->tva_npr, $object->type, false, 1); print '
'; print $langs->trans('PriceBase'); print ''; print $form->selectPriceBaseType($object->price_base_type, "price_base_type"); print '
'.$langs->trans("PriceMode").''; print img_picto('', 'dynamicprice', 'class="pictofixedwidth"'); $price_expression = new PriceExpression($db); $price_expression_list = array(0 => $langs->trans("Numeric").' ('.$langs->trans("NoDynamicPrice").')'); //Put the numeric mode as first option foreach ($price_expression->list_price_expression() as $entry) { $price_expression_list[$entry->id] = $entry->title; } $price_expression_preselection = GETPOST('eid') ? GETPOST('eid') : ($object->fk_price_expression ? $object->fk_price_expression : '0'); print $form->selectarray('eid', $price_expression_list, $price_expression_preselection); print '  '.$langs->trans("PriceExpressionEditor").''; print '
'; $text = $langs->trans('SellingPrice'); print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1); print ''; if ($object->price_base_type == 'TTC') { print ''; } else { print ''; } print '
'; $text = $langs->trans('MinPrice'); print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1); print ''; if ($object->price_base_type == 'TTC') { print ''; } else { print ''; } if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) { print '   '.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')).' '.img_warning().'
'; print $langs->trans('PriceLabel'); print ''; print ''; print '
'; print '
'; print dol_get_fiche_end(); print $form->buttonsSaveCancel(); print '
'; } elseif ($action == 'edit_level_price' && $object->getRights()->creer) { print ''."\n"; ?> id.'" method="POST">'; print ''; print ''; print ''; //print dol_get_fiche_head(array(), '', '', -1); if ((getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && getDolGlobalString('PRODUIT_MULTIPRICES_ALLOW_AUTOCALC_PRICELEVEL')) { print $langs->trans('UseMultipriceRules').' price_autogen ? 'checked' : '').'>

'; } print '
'; print ''; print ''; print ''; if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { print ''; } else { print ''; } print ''; print ''; if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) { print ''; } // fetch optionals attributes and labels $extrafields->fetch_name_optionals_label("product_price"); if ($extrafields->attributes["product_price"] && array_key_exists('label', $extrafields->attributes["product_price"])) { $extralabels = $extrafields->attributes["product_price"]['label']; if (!empty($extralabels)) { foreach ($extralabels as $key => $value) { // Show field if not hidden if (!empty($extrafields->attributes["product_price"]['list'][$key]) && $extrafields->attributes["product_price"]['list'][$key] != 3) { if (!empty($extrafields->attributes["product_price"]['langfile'][$key])) { $langs->load($extrafields->attributes["product_price"]['langfile'][$key]); } if (!empty($extrafields->attributes["product_price"]['help'][$key])) { $extratitle = $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_price"]['help'][$key])); } else { $extratitle = $langs->trans($value); } print ''; } } } } print ''; print ''; $produit_multiprices_limit = getDolGlobalInt('PRODUIT_MULTIPRICES_LIMIT'); for ($i = 1; $i <= $produit_multiprices_limit; $i++) { print ''; print ''; // VAT if (!getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { print ''; } else { // This option is kept for backward compatibility but has no sense print ''; } // Selling price print ''; // Min price print ''; } print ''; if (!empty($extralabels)) { $sql1 = "SELECT rowid"; $sql1 .= " FROM ".$object->db->prefix()."product_price"; $sql1 .= " WHERE entity IN (".getEntity('productprice').")"; $sql1 .= " AND price_level=".((int) $i); $sql1 .= " AND fk_product = ".((int) $object->id); $sql1 .= " ORDER BY date_price DESC, rowid DESC"; $sql1 .= " LIMIT 1"; $resql1 = $object->db->query($sql1); if ($resql1) { $lineid = $object->db->fetch_object($resql1); } if (empty($lineid->rowid)) { foreach ($extralabels as $key => $value) { if (!empty($extrafields->attributes["product_price"]['list'][$key]) && ($extrafields->attributes["product_price"]['list'][$key] == 1 || $extrafields->attributes["product_price"]['list'][$key] == 3 || ($action == "edit_level_price" && $extrafields->attributes["product_price"]['list'][$key] == 4))) { if (!empty($extrafields->attributes["product_price"]['langfile'][$key])) { $langs->load($extrafields->attributes["product_price"]['langfile'][$key]); } $extravalue = GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : $obj->{$key}; print ''; } } } else { $sql = "SELECT"; $sql .= " fk_object"; foreach ($extralabels as $key => $value) { $sql .= ", ".$key; } $sql .= " FROM ".MAIN_DB_PREFIX."product_price_extrafields"; $sql .= " WHERE fk_object = ".((int) $lineid->rowid); $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); foreach ($extralabels as $key => $value) { if (!empty($extrafields->attributes["product_price"]['list'][$key]) && ($extrafields->attributes["product_price"]['list'][$key] == 1 || $extrafields->attributes["product_price"]['list'][$key] == 3 || ($action == "edit_level_price" && $extrafields->attributes["product_price"]['list'][$key] == 4))) { if (!empty($extrafields->attributes["product_price"]['langfile'][$key])) { $langs->load($extrafields->attributes["product_price"]['langfile'][$key]); } $extravalue = (GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : $obj->{$key} ?? ''); print ''; } } $db->free($resql); } } } print ''; } print ''; print '
'.$langs->trans("PriceLevel").''.$langs->trans("DefaultTaxRate").''.$langs->trans("SellingPrice").''.$langs->trans("MinPrice").''.$extratitle.'
'; $keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.$i; $text = $langs->trans('SellingPrice').' '.$i.' - '.getDolGlobalString($keyforlabel); print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1); print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print $form->load_tva("tva_tx[".$i.']', $object->multiprices_tva_tx[$i], $mysoc, '', $object->id, false, $object->type, false, 1); print ''; if ($object->multiprices_base_type [$i] == 'TTC') { print ''; } else { print ''; } print ' '.$form->selectPriceBaseType($object->multiprices_base_type [$i], "multiprices_base_type[".$i."]"); print ''; if ($object->multiprices_base_type [$i] == 'TTC') { print ''; } else { print ''; } if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) { print ''.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')).' '.img_warning().'
'; print '
'; //print dol_get_fiche_end(); print $form->buttonsSaveCancel(); print ''; } } // Add area to show/add/edit a price for a dedicated customer if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { $prodcustprice = new ProductCustomerPrice($db); $limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit; $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma'); $page = (GETPOSTINT("page") ? GETPOSTINT("page") : 0); if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 $offset = $limit * $page; $pageprev = $page - 1; $pagenext = $page + 1; if (!$sortorder) { $sortorder = "ASC"; } if (!$sortfield) { $sortfield = "soc.nom"; } // Build filter to display only concerned lines $filter = array('t.fk_product' => $object->id); if (!empty($search_soc)) { $filter['soc.nom'] = $search_soc; } if ($action == 'add_customer_price') { // Form to add a new customer price $maxpricesupplier = $object->min_recommended_price(); print ''; print load_fiche_titre($langs->trans('AddCustomerPrice')); print '
'; print ''; print ''; print ''; print '
'; print ''; print ''; print ''; print ''; print ''; // Ref. Customer print ''; print ''; // VAT print ''; // Price base print ''; print ''; print ''; // Price print ''; // Price minimum print ''; } print ''; // Price Label print ''; print ''; // Extrafields $extrafields->fetch_name_optionals_label("product_customer_price"); $extralabels = !empty($extrafields->attributes["product_customer_price"]['label']) ? $extrafields->attributes["product_customer_price"]['label'] : ''; $extrafield_values = $extrafields->getOptionalsFromPost("product_customer_price"); if (!empty($extralabels)) { if (empty($prodcustprice->id)) { foreach ($extralabels as $key => $value) { if (!empty($extrafields->attributes["product_customer_price"]['list'][$key]) && ($extrafields->attributes["product_customer_price"]['list'][$key] == 1 || $extrafields->attributes["product_customer_price"]['list'][$key] == 3 || ($action == "add_customer_price" && $extrafields->attributes["product_customer_price"]['list'][$key] == 4))) { if (!empty($extrafields->attributes["product_customer_price"]['langfile'][$key])) { $langs->load($extrafields->attributes["product_customer_price"]['langfile'][$key]); } print 'attributes["product_customer_price"]['required'][$key] ? ' class="fieldrequired"' : '').'>'; if (!empty($extrafields->attributes["product_customer_price"]['help'][$key])) { print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_customer_price"]['help'][$key])); } else { print $langs->trans($value); } print ''; } } } } print '
'.$langs->trans('ThirdParty').''; $filter = '(s.client:IN:1,2,3)'; print img_picto('', 'company').$form->select_company('', 'socid', $filter, 'SelectThirdParty', 0, 0, array(), 0, 'minwidth300'); print '
' . $langs->trans('RefCustomer') . '
'.$langs->trans("DefaultTaxRate").''; print $form->load_tva("tva_tx", $object->default_vat_code ? $object->tva_tx.' ('.$object->default_vat_code.')' : $object->tva_tx, $mysoc, null, $object->id, $object->tva_npr, $object->type, false, 1); print '
'; print $langs->trans('PriceBase'); print ''; print $form->selectPriceBaseType($object->price_base_type, "price_base_type"); print '
'; $text = $langs->trans('SellingPrice'); print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1); print ''; if ($object->price_base_type == 'TTC') { print ''; } else { print ''; } print '
'; $text = $langs->trans('MinPrice'); print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1); if ($object->price_base_type == 'TTC') { print ''; } else { print ''; } if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) { print ''.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')).' '.img_warning().'
'; print $langs->trans('PriceLabel'); print ''; print ''; print '
'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : '', '', '', '', '', 0, 'product_customer_price').'
'; print '
'; print '
'; // Update all child soc print '
'; print ' '; print ''; print '
'; print $form->buttonsSaveCancel(); print ''; } elseif ($action == 'edit_customer_price') { // Edit mode $maxpricesupplier = $object->min_recommended_price(); print ''; print load_fiche_titre($langs->trans('PriceByCustomer')); $result = $prodcustprice->fetch(GETPOSTINT('lineid')); if ($result < 0) { setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors'); } print '
'; print ''; print ''; print ''; print ''; print ''; print ''; $staticsoc = new Societe($db); $staticsoc->fetch($prodcustprice->fk_soc); print ""; print ''; // Ref. Customer print ''; print ''; // VAT print ''; // Price base print ''; print ''; print ''; // Price print ''; // Price minimum print ''; if (getDolGlobalString('PRODUCT_MINIMUM_RECOMMENDED_PRICE')) { print ''; } print ''; // Price Label print ''; print ''; // Extrafields $extrafields->fetch_name_optionals_label("product_customer_price"); $extralabels = !empty($extrafields->attributes["product_customer_price"]['label']) ? $extrafields->attributes["product_customer_price"]['label'] : ''; $extrafield_values = $extrafields->getOptionalsFromPost("product_customer_price"); if (!empty($extralabels)) { if (empty($object->id)) { foreach ($extralabels as $key => $value) { if (!empty($extrafields->attributes["product_customer_price"]['list'][$key]) && ($extrafields->attributes["product_customer_price"]['list'][$key] == 1 || $extrafields->attributes["product_customer_price"]['list'][$key] == 3 || ($action == "edit_price" && $extrafields->attributes["product_customer_price"]['list'][$key] == 4))) { if (!empty($extrafields->attributes["product_customer_price"]['langfile'][$key])) { $langs->load($extrafields->attributes["product_customer_price"]['langfile'][$key]); } print 'attributes["product_customer_price"]['required'][$key] ? ' class="fieldrequired"' : '').'>'; if (!empty($extrafields->attributes["product_customer_price"]['help'][$key])) { print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_customer_price"]['help'][$key])); } else { print $langs->trans($value); } print ''; } } } else { $sql = "SELECT"; $sql .= " fk_object"; foreach ($extralabels as $key => $value) { $sql .= ", ".$key; } $sql .= " FROM ".MAIN_DB_PREFIX."product_customer_price_extrafields"; $sql .= " WHERE fk_object = ".((int) $prodcustprice->id); $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); foreach ($extralabels as $key => $value) { if (!empty($extrafields->attributes["product_customer_price"]['list'][$key]) && ($extrafields->attributes["product_customer_price"]['list'][$key] == 1 || $extrafields->attributes["product_customer_price"]['list'][$key] == 3 || ($action == "edit_price" && $extrafields->attributes["product_customer_price"]['list'][$key] == 4))) { if (!empty($extrafields->attributes["product_customer_price"]['langfile'][$key])) { $langs->load($extrafields->attributes["product_customer_price"]['langfile'][$key]); } print 'attributes["product_customer_price"]['required'][$key] ? ' class="fieldrequired"' : '').'>'; if (!empty($extrafields->attributes["product_customer_price"]['help'][$key])) { print $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_customer_price"]['help'][$key])); } else { print $langs->trans($value); } print ''; } } $db->free($resql); } } } print '
'.$langs->trans('ThirdParty').'".$staticsoc->getNomUrl(1)."
' . $langs->trans('RefCustomer') . '
'.$langs->trans("DefaultTaxRate").''; print $form->load_tva("tva_tx", $prodcustprice->default_vat_code ? $prodcustprice->tva_tx.' ('.$prodcustprice->default_vat_code.')' : $prodcustprice->tva_tx, $mysoc, null, $object->id, $prodcustprice->recuperableonly, $object->type, false, 1); print '
'; print $langs->trans('PriceBase'); print ''; print $form->selectPriceBaseType($prodcustprice->price_base_type, "price_base_type"); print '
'; $text = $langs->trans('SellingPrice'); print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1); print ''; if ($prodcustprice->price_base_type == 'TTC') { print ''; } else { print ''; } print '
'; $text = $langs->trans('MinPrice'); print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", getDolGlobalString('MAIN_MAX_DECIMALS_UNIT')), 1, 1); print ''; if ($prodcustprice->price_base_type == 'TTC') { print ''; } else { print ''; } print ''.$langs->trans("MinimumRecommendedPrice", price($maxpricesupplier, 0, '', 1, -1, -1, 'auto')).' '.img_warning().'
'; print $langs->trans('PriceLabel'); print ''; print ''; print '
'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : '', '', '', '', '', 0, 'product_customer_price').'
'.$extrafields->showInputField($key, GETPOSTISSET('options_'.$key) ? $extrafield_values['options_'.$key] : $obj->{$key}, '', '', '', '', 0, 'product_customer_price'); print '
'; print '
'; print '
'; print ' '; print ''; print "
"; print $form->buttonsSaveCancel(); print '
'; } elseif ($action == 'showlog_customer_price') { // List of all log of prices by customers print ''."\n"; $filter = array('t.fk_product' => $object->id, 't.fk_soc' => GETPOSTINT('socid')); // Count total nb of records $nbtotalofrecords = ''; if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { $nbtotalofrecords = $prodcustprice->fetchAllLog($sortorder, $sortfield, $conf->liste_limit, $offset, $filter); } $result = $prodcustprice->fetchAllLog($sortorder, $sortfield, $conf->liste_limit, $offset, $filter); if ($result < 0) { setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors'); } $option = '&socid='.GETPOSTINT('socid').'&id='.$object->id; $staticsoc = new Societe($db); $staticsoc->fetch(GETPOSTINT('socid')); $title = $langs->trans('PriceByCustomerLog'); $title .= ' - '.$staticsoc->getNomUrl(1); $backbutton = ''.$langs->trans("Back").''; // @phan-suppress-next-line PhanPluginSuspiciousParamOrder print_barre_liste($title, $page, $_SERVER['PHP_SELF'], $option, $sortfield, $sortorder, $backbutton, count($prodcustprice->lines), $nbtotalofrecords, 'title_accountancy.png'); if (count($prodcustprice->lines) > 0) { print '
'; print ''; print ''; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { print ''; } print ''; print ''; print ''; print ''; print ''; print ''; foreach ($prodcustprice->lines as $line) { // Date $staticsoc = new Societe($db); $staticsoc->fetch($line->fk_soc); $tva_tx = $line->default_vat_code ? $line->tva_tx.' ('.$line->default_vat_code.')' : $line->tva_tx; // Line for default price if ($line->price_base_type == 'HT') { $pu = $line->price; } else { $pu = $line->price_ttc; } // Local tax is not saved into table of product. We use value linked to VAT code. $localtaxarray = getLocalTaxesFromRate($line->tva_tx.($line->default_vat_code ? ' ('.$line->default_vat_code.')' : ''), 0, $staticsoc, $mysoc); // Define part of HT, VAT, TTC $resultarray = calcul_price_total(1, $pu, 0, $line->tva_tx, 1, 1, 0, $line->price_base_type, $line->recuperableonly, $object->type, $mysoc, $localtaxarray); // Calcul du total ht sans remise $total_ht = $resultarray[0]; $total_vat = $resultarray[1]; $total_localtax1 = $resultarray[9]; $total_localtax2 = $resultarray[10]; $total_ttc = $resultarray[2]; print ''; print '"; print ''; print ""; print '"; print '"; print '"; print '"; if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { print ''; } print ''; print ''; print ''; // User $userstatic = new User($db); $userstatic->fetch($line->fk_user); print ''; print ''; } print "
'.$langs->trans("ThirdParty").''.$langs->trans('RefCustomer').''.$langs->trans("AppliedPricesFrom").''.$langs->trans("PriceBase").''.$langs->trans("DefaultTaxRate").''.$langs->trans("HT").''.$langs->trans("TTC").''.$langs->trans("INCT").''.$langs->trans("MinPrice").' '.$langs->trans("HT").''.$langs->trans("MinPrice").' '.$langs->trans("TTC").''.$langs->trans("PriceLabel").''.$langs->trans("ChangedBy").' 
'.$staticsoc->getNomUrl(1)."'.$line->ref_customer.'".dol_print_date($line->datec, "dayhour", 'tzuserrel')."'.$langs->trans($line->price_base_type)."'; $positiverates = ''; if (price2num($line->tva_tx)) { $positiverates .= ($positiverates ? '/' : '').price2num($line->tva_tx); } if (price2num($line->localtax1_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($line->localtax1_tx); } if (price2num($line->localtax2_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($line->localtax2_tx); } if (empty($positiverates)) { $positiverates = '0'; } echo vatrate($positiverates.($line->default_vat_code ? ' ('.$line->default_vat_code.')' : ''), true, ($line->tva_npr ? $line->tva_npr : $line->recuperableonly)); //. vatrate($tva_tx, true, $line->recuperableonly) . print "'.price($line->price)."'.price($line->price_ttc)."'.price($resultarray[2]).''.price($line->price_min).''.price($line->price_min_ttc).''.$line->price_label.''; print $userstatic->getNomUrl(1, '', 0, 0, 24, 0, 'login'); //print $userstatic->getLoginUrl(1); print '
"; print '
'; } else { print $langs->trans('None'); } } elseif ($action != 'showlog_default_price' && $action != 'edit_price' && $action != 'edit_level_price') { // List of all prices by customers print ''."\n"; // Count total nb of records $nbtotalofrecords = ''; if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { $nbtotalofrecords = $prodcustprice->fetchAll($sortorder, $sortfield, 0, 0, $filter); } $result = $prodcustprice->fetchAll($sortorder, $sortfield, $conf->liste_limit, $offset, $filter); if ($result < 0) { setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors'); } $option = '&search_soc='.$search_soc.'&id='.$object->id; // @phan-suppress-next-line PhanPluginSuspiciousParamOrder print_barre_liste($langs->trans('PriceByCustomer'), $page, $_SERVER ['PHP_SELF'], $option, $sortfield, $sortorder, '', count($prodcustprice->lines), $nbtotalofrecords, 'title_accountancy.png'); print ''; print ''; print ''; print ''."\n"; print '
'."\n"; print ''."\n"; if (count($prodcustprice->lines) > 0 || $search_soc) { $extrafields->fetch_name_optionals_label("product_customer_price"); $custom_price_extralabels = !empty($extrafields->attributes["product_customer_price"]['label']) ? $extrafields->attributes["product_customer_price"]['label'] : ''; if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { $colspan = 10; } else { $colspan = 11; } if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { $colspan++; } if (!empty($custom_price_extralabels) && is_array($custom_price_extralabels)) { $colspan += count($custom_price_extralabels); } print ''; print ''; print ''; // Print the search button print ''; print ''; } print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { print ''; } print ''; print ''; print ''; // fetch optionals attributes and labels $extrafields->fetch_name_optionals_label("product_customer_price"); if ($extrafields->attributes["product_customer_price"] && array_key_exists('label', $extrafields->attributes["product_customer_price"])) { $extralabels = $extrafields->attributes["product_customer_price"]['label']; if (!empty($extralabels)) { foreach ($extralabels as $key => $value) { // Show field if not hidden if (!empty($extrafields->attributes["product_customer_price"]['list'][$key]) && $extrafields->attributes["product_customer_price"]['list'][$key] != 3) { if (!empty($extrafields->attributes["product_customer_price"]['langfile'][$key])) { $langs->load($extrafields->attributes["product_customer_price"]['langfile'][$key]); } if (!empty($extrafields->attributes["product_customer_price"]['help'][$key])) { $extratitle = $form->textwithpicto($langs->trans($value), $langs->trans($extrafields->attributes["product_customer_price"]['help'][$key])); } else { $extratitle = $langs->trans($value); } print ''; } } } } print ''; print ''; print ''; // Line for default price if ($object->price_base_type == 'HT') { $pu = $object->price; } else { $pu = $object->price_ttc; } // Local tax was not saved into table llx_product on old versions. So we will use the value linked to the VAT code. $localtaxarray = getLocalTaxesFromRate($object->tva_tx.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), 0, $mysoc, $mysoc); // Define part of HT, VAT, TTC $resultarray = calcul_price_total(1, $pu, 0, $object->tva_tx, 1, 1, 0, $object->price_base_type, 0, $object->type, $mysoc, $localtaxarray); // Calcul du total ht sans remise $total_ht = $resultarray[0]; $total_vat = $resultarray[1]; $total_localtax1 = $resultarray[9]; $total_localtax2 = $resultarray[10]; $total_ttc = $resultarray[2]; if (!getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { print ''."\n"; print ''; print ''; print '"; // VAT Rate print '"; print '"; print '"; if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { //print '"; print ''; } print ''; print ''; print ''; print ''; if (!empty($extralabels)) { foreach ($extralabels as $key) { // Show field if not hidden if (!empty($extrafields->attributes["product_customer_price"]['list'][$key]) && $extrafields->attributes["product_customer_price"]['list'][$key] != 3) { print ''; } } } if ($user->hasRight('produit', 'supprimer') || $user->hasRight('service', 'supprimer')) { print ''; } print "\n"; } if (count($prodcustprice->lines) > 0) { foreach ($prodcustprice->lines as $line) { // Date $staticsoc = new Societe($db); $staticsoc->fetch($line->fk_soc); $tva_tx = $line->default_vat_code ? $line->tva_tx.' ('.$line->default_vat_code.')' : $line->tva_tx; // Line for default price if ($line->price_base_type == 'HT') { $pu = $line->price; } else { $pu = $line->price_ttc; } // Local tax is not saved into table of product. We use value linked to VAT code. $localtaxarray = getLocalTaxesFromRate($line->tva_tx.($line->default_vat_code ? ' ('.$line->default_vat_code.')' : ''), 0, $staticsoc, $mysoc); // Define part of HT, VAT, TTC $resultarray = calcul_price_total(1, $pu, 0, $line->tva_tx, 1, 1, 0, $line->price_base_type, $line->recuperableonly, $object->type, $mysoc, $localtaxarray); // Calcul du total ht sans remise $total_ht = $resultarray[0]; $total_vat = $resultarray[1]; $total_localtax1 = $resultarray[9]; $total_localtax2 = $resultarray[10]; $total_ttc = $resultarray[2]; print ''; print '"; print ''; print ""; print '"; // VAT Rate print '"; print '"; print '"; if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { //print '"; print ''; } print ''; print ''; print ''; // Extrafields $extrafields->fetch_name_optionals_label("product_customer_price"); $extralabels = $extrafields->attributes["product_customer_price"]['label'] ?? array(); if (!empty($extralabels)) { $sql = "SELECT"; $sql .= " fk_object"; foreach ($extralabels as $key => $value) { $sql .= ", ".$key; } $sql .= " FROM ".MAIN_DB_PREFIX."product_customer_price_extrafields"; $sql .= " WHERE fk_object = ".((int) $line->id); $resql = $db->query($sql); if ($resql) { if ($db->num_rows($resql) != 1) { foreach ($extralabels as $key => $value) { if (!empty($extrafields->attributes["product_customer_price"]['list'][$key]) && $extrafields->attributes["product_customer_price"]['list'][$key] != 3) { print ""; } } } else { $obj = $db->fetch_object($resql); foreach ($extralabels as $key => $value) { if (!empty($extrafields->attributes["product_customer_price"]['list'][$key]) && $extrafields->attributes["product_customer_price"]['list'][$key] != 3) { print '"; } } } $db->free($resql); } } // User $userstatic = new User($db); $userstatic->fetch($line->fk_user); // @TODO Add a cache on $users object print ''; // Todo Edit or delete button // Action if ($user->hasRight('produit', 'supprimer') || $user->hasRight('service', 'supprimer')) { print ''; } print "\n"; } } print "
 '; $searchpicto = $form->showFilterAndCheckAddButtons(0); print $searchpicto; print '
'.$langs->trans("ThirdParty").''.$langs->trans('RefCustomer').''.$langs->trans("AppliedPricesFrom").''.$langs->trans("PriceBase").''.$langs->trans("DefaultTaxRate").''.$langs->trans("HT").''.$langs->trans("TTC").''.$langs->trans("INCT").''.$langs->trans("MinPrice").' '.$langs->trans("HT").''.$langs->trans("MinPrice").' '.$langs->trans("TTC").''.$langs->trans("PriceLabel").''.$extratitle.''.$langs->trans("ChangedBy").'
' . $langs->trans('Default') . ''.$langs->trans($object->price_base_type)."'; $positiverates = ''; if (price2num($object->tva_tx)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->tva_tx); } if (price2num($object->localtax1_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax1_tx); } if (price2num($object->localtax2_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($object->localtax2_tx); } if (empty($positiverates)) { $positiverates = '0'; } echo vatrate($positiverates.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), true, $object->tva_npr); //print vatrate($object->tva_tx, true, $object->tva_npr); //print $object->default_vat_code?' ('.$object->default_vat_code.')':''; print "'.price($object->price)."'.price($object->price_ttc)."' . price($object->price_ttc) . "'.price($resultarray[2]).''.price($object->price_min).''.price($object->price_min_ttc).''.$object->price_label.''; print 'id.'">'; print img_info($langs->trans('PriceByCustomerLog')); print ''; print ' '; print 'id.'">'; print img_edit('default', 0, 'style="vertical-align: middle;"'); print ''; print '
'.$staticsoc->getNomUrl(1)."'.dol_escape_htmltag($line->ref_customer).'".dol_print_date($line->datec, "dayhour", 'tzuserrel')."'.$langs->trans($line->price_base_type)."'; $positiverates = ''; if (price2num($line->tva_tx)) { $positiverates .= ($positiverates ? '/' : '').price2num($line->tva_tx); } if (price2num($line->localtax1_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($line->localtax1_tx); } if (price2num($line->localtax2_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($line->localtax2_tx); } if (empty($positiverates)) { $positiverates = '0'; } echo vatrate($positiverates.($line->default_vat_code ? ' ('.$line->default_vat_code.')' : ''), true, (!empty($line->tva_npr) ? $line->tva_npr : $line->recuperableonly)); print "'.price($line->price)."'.price($line->price_ttc)."' . price($line->price_ttc) . "'.price($resultarray[2]).''.price($line->price_min).''.price($line->price_min_ttc).''.$line->price_label.''.$extrafields->showOutputField($key, $obj->{$key}, '', 'product_customer_price')."'; print $userstatic->getNomUrl(-1, '', 0, 0, 24, 0, 'login'); print ''; print 'id.'&socid='.$line->fk_soc.'">'; print img_info($langs->trans('PriceByCustomerLog')); print ''; print ' '; print 'id.'&lineid='.$line->id.'">'; print img_edit('default', 0, 'style="vertical-align: middle;"'); print ''; print ' '; print 'id.'&lineid='.$line->id.'">'; print img_delete('default', 'style="vertical-align: middle;"'); print ''; print '
"; print '
'; print "
"; } } // List of price changes - log historic (ordered by descending date) if ((!getDolGlobalString('PRODUIT_CUSTOMER_PRICES') || $action == 'showlog_default_price') && !in_array($action, array('edit_price', 'edit_level_price', 'edit_vat'))) { $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,"; $sql .= " p.price_level, p.price_min, p.price_min_ttc,p.price_by_qty,"; $sql .= " p.date_price as dp, p.fk_price_expression, u.rowid as user_id, u.login"; $sql .= " ,p.price_label"; $sql .= " FROM ".MAIN_DB_PREFIX."product_price as p,"; $sql .= " ".MAIN_DB_PREFIX."user as u"; $sql .= " WHERE fk_product = ".((int) $object->id); $sql .= " AND p.entity IN (".getEntity('productprice').")"; $sql .= " AND p.fk_user_author = u.rowid"; if (!empty($socid) && (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) && $soc !== null) { $sql .= " AND p.price_level = ".((int) $soc->price_level); } $sql .= " ORDER BY p.date_price DESC, p.rowid DESC, p.price_level ASC"; // $sql .= $db->plimit(); //print $sql; $result = $db->query($sql); if ($result) { print '
'; $num = $db->num_rows($result); if (!$num) { $db->free($result); // Il doit au moins y avoir la ligne de prix initial. // On l'ajoute donc pour remettre a niveau (pb vieilles versions) // We emulate the change of the price from interface with the same value than the one into table llx_product if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { $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); } else { $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)); } if ($ret < 0) { dol_print_error($db, $object->error, $object->errors); } else { $result = $db->query($sql); $num = $db->num_rows($result); } } if ($num > 0) { // Default prices or // Log of previous customer prices $backbutton = ''.$langs->trans("Back").''; if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES')) { // @phan-suppress-next-line PhanPluginSuspiciousParamPosition, PhanPluginSuspiciousParamOrder print_barre_liste($langs->trans("DefaultPriceLog"), 0, $_SERVER["PHP_SELF"], '', '', '', $backbutton, 0, $num, 'title_accountancy.png'); } else { // @phan-suppress-next-line PhanPluginSuspiciousParamPosition, PhanPluginSuspiciousParamOrder print_barre_liste($langs->trans("PriceByCustomerLog"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, $num, 'title_accountancy.png'); } print ''."\n"; print '
'."\n"; print ''."\n"; print ''; print ''; } if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { print ''; } print ''; if (!getDolGlobalString('PRODUIT_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { print ''; } print ''; print ''; if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { print ''; } if (isModEnabled('dynamicprices')) { print ''; } print ''; print ''; print ''; print ''; if ($user->hasRight('produit', 'supprimer')) { print ''; } print ''; $notfirstlineforlevel = array(); $i = 0; while ($i < $num) { $objp = $db->fetch_object($result); print ''; // Date print ""; // Price level if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { print '"; } // Price by quantity if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { $type = ($objp->price_by_qty == 1) ? 'PriceByQuantity' : 'Standard'; print '"; } print '"; if (!getDolGlobalString('PRODUIT_MULTIPRICES') && !getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { print '"; } // Line for default price if ($objp->price_base_type == 'HT') { $pu = $objp->price; } else { $pu = $objp->price_ttc; } // Local tax was not saved into table llx_product on old version. So we will use value linked to VAT code. $localtaxarray = getLocalTaxesFromRate($objp->tva_tx.($object->default_vat_code ? ' ('.$object->default_vat_code.')' : ''), 0, $mysoc, $mysoc); // Define part of HT, VAT, TTC $resultarray = calcul_price_total(1, $pu, 0, $objp->tva_tx, 1, 1, 0, $objp->price_base_type, $objp->recuperableonly, $object->type, $mysoc, $localtaxarray); // Calcul du total ht sans remise $total_ht = $resultarray[0]; $total_vat = $resultarray[1]; $total_localtax1 = $resultarray[9]; $total_localtax2 = $resultarray[10]; $total_ttc = $resultarray[2]; // Price if (!empty($objp->fk_price_expression) && !empty($conf->dynamicprices->enabled)) { $price_expression = new PriceExpression($db); $res = $price_expression->fetch($objp->fk_price_expression); $title = $price_expression->title; print ''; print ''; if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { print ''; } print '"; } else { // Price HT print '"; // Price TTC print '"; if ($mysoc->localtax1_assuj == "1" || $mysoc->localtax2_assuj == "1") { print ''; } if (isModEnabled('dynamicprices')) { // Only if module is enabled print ''; } } // Price min print ''; // Price min inc tax print ''; // Price Label print ''; // User print ''; // Action if ($user->hasRight('produit', 'supprimer')) { $candelete = 0; if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { if (empty($notfirstlineforlevel[$objp->price_level])) { $notfirstlineforlevel[$objp->price_level] = 1; } else { $candelete = 1; } } elseif ($i > 0) { $candelete = 1; } print ''; } print "\n"; $i++; } $db->free($result); print "
'.$langs->trans("AppliedPricesFrom").''; if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) { print ''.$langs->trans("PriceLevel").''.$langs->trans("Type").''.$langs->trans("PriceBase").''.$langs->trans("DefaultTaxRate").''.$langs->trans("HT").''.$langs->trans("TTC").''.$langs->trans("INCT").''.$langs->trans("PriceExpressionSelected").''.$langs->trans("MinPrice").' '.$langs->trans("HT").''.$langs->trans("MinPrice").' '.$langs->trans("TTC").''.$langs->trans("Label").''.$langs->trans("ChangedBy").' 
".dol_print_date($db->jdate($objp->dp), "dayhour", 'tzuserrel')."'.$objp->price_level."'.$langs->trans($type)."'; if (empty($objp->price_by_qty)) { print $langs->trans($objp->price_base_type); } print "'; if (empty($objp->price_by_qty)) { $positiverates = ''; if (price2num($objp->tva_tx)) { $positiverates .= ($positiverates ? '/' : '').price2num($objp->tva_tx); } if (price2num($objp->localtax1_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($objp->localtax1_tx); } if (price2num($objp->localtax2_type)) { $positiverates .= ($positiverates ? '/' : '').price2num($objp->localtax2_tx); } if (empty($positiverates)) { $positiverates = '0'; } echo vatrate($positiverates.($objp->default_vat_code ? ' ('.$objp->default_vat_code.')' : ''), true, !empty($objp->tva_npr) ? $objp->tva_npr : 0); /* if ($objp->default_vat_code) { print vatrate($objp->tva_tx, true) . ' ('.$objp->default_vat_code.')'; } else print vatrate($objp->tva_tx, true, $objp->recuperableonly);*/ } print "'.$title."'; if (empty($objp->price_by_qty)) { print ''.price($objp->price).''; } print "'; if (empty($objp->price_by_qty)) { $price_ttc = $objp->price_ttc; print ''.price($price_ttc).''; } print "'; print $resultarray[2]; print ''; if (empty($objp->price_by_qty)) { print price($objp->price_min); } print ''; if (empty($objp->price_by_qty)) { $price_min_ttc = $objp->price_min_ttc; print price($price_min_ttc); } print ''; print $objp->price_label; print ''; if ($objp->user_id > 0) { $userstatic = new User($db); $userstatic->fetch($objp->user_id); print $userstatic->getNomUrl(-1, '', 0, 0, 24, 0, 'login'); } print ''; 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 print 'id.'&lineid='.$objp->rowid.'">'; print img_delete(); print ''; } else { print ' '; // Can not delete last price (it's current price) } print '
"; print '
'; print "
"; } print '
'; } else { dol_print_error($db); } } // End of page llxFooter(); $db->close();