diff --git a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql index fea6c1a51e6..14fc29dedf8 100644 --- a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql +++ b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql @@ -71,6 +71,22 @@ ALTER TABLE llx_website_page ADD COLUMN type_container varchar(16) NOT NULL DEFA -- For 7.0 +ALTER TABLE llx_product_price_by_qty ADD COLUMN quantity double DEFAULT NULL; +ALTER TABLE llx_product_price_by_qty ADD COLUMN unitprice double(24,8) DEFAULT 0; + +ALTER TABLE llx_product_price_by_qty ADD COLUMN price_base_type varchar(3) DEFAULT 'HT'; +ALTER TABLE llx_product_price_by_qty ADD COLUMN fk_multicurrency integer; +ALTER TABLE llx_product_price_by_qty ADD COLUMN multicurrency_code varchar(255); +ALTER TABLE llx_product_price_by_qty ADD COLUMN multicurrency_tx double(24,8) DEFAULT 1; +ALTER TABLE llx_product_price_by_qty ADD COLUMN multicurrency_price double(24,8) DEFAULT NULL; +ALTER TABLE llx_product_price_by_qty ADD COLUMN multicurrency_price_ttc double(24,8) DEFAULT NULL; + +-- VMYSQL4.0 DROP INDEX uk_product_price_by_qty_level on llx_product_price_by_qty; +-- VPGSQL8.0 DROP INDEX uk_product_price_by_qty_level; + +ALTER TABLE llx_product_price_by_qty ADD UNIQUE INDEX uk_product_price_by_qty_level (fk_product_price, quantity); + + ALTER TABLE llx_accounting_bookkeeping ADD INDEX idx_accounting_bookkeeping_fk_doc (fk_doc); ALTER TABLE llx_c_revenuestamp ADD COLUMN revenuestamp_type varchar(16) DEFAULT 'fixed' NOT NULL; diff --git a/htdocs/install/mysql/tables/llx_product_price_by_qty.sql b/htdocs/install/mysql/tables/llx_product_price_by_qty.sql index 2b91647b80a..9dbeb530a34 100644 --- a/htdocs/install/mysql/tables/llx_product_price_by_qty.sql +++ b/htdocs/install/mysql/tables/llx_product_price_by_qty.sql @@ -17,6 +17,8 @@ -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- +-- This table is used to defined price by qty when a line into llx_product_price +-- is set with price_by_qty = 1 -- ============================================================================ create table llx_product_price_by_qty @@ -24,12 +26,20 @@ create table llx_product_price_by_qty rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, fk_product_price integer NOT NULL, price double(24,8) DEFAULT 0, + price_base_type varchar(3) DEFAULT 'HT', quantity double DEFAULT NULL, remise_percent double NOT NULL DEFAULT 0, remise double NOT NULL DEFAULT 0, unitprice double(24,8) DEFAULT 0, fk_user_creat integer, fk_user_modif integer, + + fk_multicurrency integer, + multicurrency_code varchar(255), + multicurrency_tx double(24,8) DEFAULT 1, + multicurrency_price double(24,8) DEFAULT NULL, + multicurrency_price_ttc double(24,8) DEFAULT NULL, + tms timestamp, import_key varchar(14) )ENGINE=innodb; diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index a1d81183c41..179175041b8 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -196,6 +196,7 @@ CurrentProductPrice=Current price AlwaysUseNewPrice=Always use current price of product/service AlwaysUseFixedPrice=Use the fixed price PriceByQuantity=Different prices by quantity +DisablePriceByQty=Disable prices by quantity PriceByQuantityRange=Quantity range MultipriceRules=Price segment rules UseMultipriceRules=Use price segment rules (defined into product module setup) to autocalculate prices of all other segment according to first segment diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php index 78829e489a6..abfe82d0dff 100644 --- a/htdocs/product/admin/product.php +++ b/htdocs/product/admin/product.php @@ -36,8 +36,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formbarcode.class.php'; -$langs->load("admin"); -$langs->load("products"); +$langs->loadLangs(array("admin","products")); // Security check if (! $user->admin || (empty($conf->product->enabled) && empty($conf->service->enabled))) @@ -55,12 +54,10 @@ $select_pricing_rules=array( 'PRODUIT_MULTIPRICES'=>$langs->trans('MultiPricesAbility'), // Several prices according to a customer level 'PRODUIT_CUSTOMER_PRICES'=>$langs->trans('PriceByCustomer'), // Different price for each customer ); -if ($conf->global->MAIN_FEATURES_LEVEL >= 2) -{ - $langs->load("admin"); - $select_pricing_rules['PRODUIT_CUSTOMER_PRICES_BY_QTY'] = $langs->trans('PriceByQuantity').' ('.$langs->trans("VersionExperimental").')'; // TODO If this is enabled, price must be hidden when price by qty is enabled, also price for quantity must be used when adding product into order/propal/invoice - $select_pricing_rules['PRODUIT_CUSTOMER_PRICES_BY_QTY&PRODUIT_MULTIPRICES'] = $langs->trans('MultiPricesAbility') . '+' . $langs->trans('PriceByQuantity').' ('.$langs->trans("VersionExperimental").')'; -} +$keyforparam='PRODUIT_CUSTOMER_PRICES_BY_QTY'; +if ($conf->global->MAIN_FEATURES_LEVEL >= 2 || ! empty($conf->global->$keyforparam)) $select_pricing_rules['PRODUIT_CUSTOMER_PRICES_BY_QTY'] = $langs->trans('PriceByQuantity').' ('.$langs->trans("VersionExperimental").')'; // TODO If this is enabled, price must be hidden when price by qty is enabled, also price for quantity must be used when adding product into order/propal/invoice +$keyforparam='PRODUIT_CUSTOMER_PRICES_BY_QTY&PRODUIT_MULTIPRICES'; +if ($conf->global->MAIN_FEATURES_LEVEL >= 2 || ! empty($conf->global->$keyforparam)) $select_pricing_rules['PRODUIT_CUSTOMER_PRICES_BY_QTY&PRODUIT_MULTIPRICES'] = $langs->trans('MultiPricesAbility') . '+' . $langs->trans('PriceByQuantity').' ('.$langs->trans("VersionExperimental").')'; // Clean param if (! empty($conf->global->PRODUIT_MULTIPRICES) && empty($conf->global->PRODUIT_MULTIPRICES_LIMIT)) { diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 6868005f54f..ab6430d9d83 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1483,12 +1483,14 @@ class Product extends CommonObject * @param int $rowid Line id to delete * @return int <0 if KO, >0 if OK */ - function log_price_delete($user,$rowid) + function log_price_delete($user, $rowid) { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price_by_qty"; + $sql.= " WHERE fk_product_price=".$rowid; + $resql=$this->db->query($sql); + $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price"; $sql.= " WHERE rowid=".$rowid; - - dol_syslog(get_class($this)."::log_price_delete", LOG_DEBUG); $resql=$this->db->query($sql); if ($resql) { @@ -1499,7 +1501,6 @@ class Product extends CommonObject $this->error=$this->db->lasterror(); return -1; } - } @@ -1642,13 +1643,13 @@ class Product extends CommonObject * @param double $newminprice New price min * @param int $level 0=standard, >0 = level if multilevel prices * @param int $newnpr 0=Standard vat rate, 1=Special vat rate for French NPR VAT - * @param int $newpsq 1 if it has price by quantity + * @param int $newpbq 1 if it has price by quantity * @param int $ignore_autogen Used to avoid infinite loops * @param array $localtaxes_array Array with localtaxes info array('0'=>type1,'1'=>rate1,'2'=>type2,'3'=>rate2) (loaded by getLocalTaxesFromRate(vatrate, 0, ...) function). * @param string $newdefaultvatcode Default vat code * @return int <0 if KO, >0 if OK */ - function updatePrice($newprice, $newpricebase, $user, $newvat='',$newminprice='', $level=0, $newnpr=0, $newpsq=0, $ignore_autogen=0, $localtaxes_array=array(), $newdefaultvatcode='') + function updatePrice($newprice, $newpricebase, $user, $newvat='',$newminprice='', $level=0, $newnpr=0, $newpbq=0, $ignore_autogen=0, $localtaxes_array=array(), $newdefaultvatcode='') { global $conf,$langs; @@ -1667,7 +1668,7 @@ class Product extends CommonObject // Price will be modified ONLY when the first one is the one that is being modified if (!empty($conf->global->PRODUIT_MULTIPRICES) && !$ignore_autogen && $this->price_autogen && ($level == 1)) { - return $this->generateMultiprices($user, $newprice, $newpricebase, $newvat, $newnpr, $newpsq); + return $this->generateMultiprices($user, $newprice, $newpricebase, $newvat, $newnpr, $newpbq); } if (! empty($newminprice) && ($newminprice > $newprice)) @@ -1781,7 +1782,7 @@ class Product extends CommonObject $this->localtax2_type = $localtaxtype2; // Price by quantity - $this->price_by_qty = $newpsq; + $this->price_by_qty = $newpbq; $this->_log_price($user,$level); // Save price for level into table product_price diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 3b33ea952b2..6b77ee3a0ee 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -379,32 +379,35 @@ if (empty($reshook)) if ($action == 'delete' && $user->rights->produit->supprimer) { - $result = $object->log_price_delete($user, $_GET ["lineid"]); + $result = $object->log_price_delete($user, GETPOST('lineid','int')); if ($result < 0) { setEventMessages($object->error, $object->errors, 'errors'); } } - /** - * *************************************************** - * Price by quantity - * *************************************************** - */ - if ($action == 'activate_price_by_qty') { // Activating product price by quantity add a new price, specified as by quantity - - $level = GETPOST('level'); - + // 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 = GETPOST('level','int'); $object->updatePrice(0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 1); } + // 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 = GETPOST('level','int'); + $object->updatePrice(0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 0); + } if ($action == 'edit_price_by_qty') { // Edition d'un prix par quantité - $rowid = GETPOST('rowid'); + $rowid = GETPOST('rowid','int'); } + // Add or update price by quantity if ($action == 'update_price_by_qty') - { // Ajout / Mise à jour d'un prix par quantité - + { // Récupération des variables $rowid = GETPOST('rowid'); $priceid = GETPOST('priceid'); @@ -415,11 +418,11 @@ if (empty($reshook)) $remise = 0; // TODO : allow discount by amount when available on documents if (empty($quantity)) { - $error ++; + $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Qty")), null, 'errors'); } if (empty($newprice)) { - $error ++; + $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Price")), null, 'errors'); } if (! $error) { @@ -442,11 +445,13 @@ if (empty($reshook)) $sql .= " WHERE rowid = " . GETPOST('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 .= $priceid . ',' . $price . ',' . $unitPrice . ',' . $quantity . ',' . $remise_percent . ',' . $remise . ')'; $result = $db->query($sql); + if (! $result) dol_print_error($db); } } } @@ -920,8 +925,8 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) if ($action != 'edit_price_by_qty' && ($user->rights->produit->creer || $user->rights->service->creer)) { print '
'; print ''; - print ''; - print ''; + print ''; // id in product_price + print ''; // id in product_price print ''; print ''; print ' ' . $object->price_base_type . ''; @@ -935,7 +940,7 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) print ''; } else { print $langs->trans("No"); - print ' (' . $langs->trans("Activate") . ')'; + print '  (' . $langs->trans("Activate") . ')'; } print ''; } @@ -983,40 +988,66 @@ else if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) // TODO Fix the form inside tr instead of td { print '' . $langs->trans("PriceByQuantity"); - if ($object->prices_by_qty [0] == 0) { - print ' ' . $langs->trans("Activate"); + if ($object->prices_by_qty[0] == 0) { + print '  (' . $langs->trans("Activate").')'; + } + else + { + print '  (' . $langs->trans("DisablePriceByQty").')'; } print ''; - if ($object->prices_by_qty [0] == 1) { + if ($object->prices_by_qty [0] == 1) + { print ''; print ''; - print ''; - 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') { + print ''; // FIXME a form into a table is not allowed + 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->rights->produit->creer || $user->rights->service->creer)) { print ''; print ''; - print ''; - print ''; - print ''; + print ''; // id in product_price + print ''; // id in product_price_by_qty + print ''; print ''; - print ''; - // print ''; + print ''; + print ''; + print ''; print ''; print ''; print ''; print ''; } else { - 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 ''; - print ''; - print ''; - print ''; - // print ''; - print ''; - print ''; - print ''; - print ''; - } - print '
' . $langs->trans("PriceByQuantityRange") . '' . $langs->trans("HT") . '' . $langs->trans("PriceByQuantityRange") . '' . $langs->trans("Quantity") . '' . $langs->trans("Price") . '' . $langs->trans("UnitPrice") . '' . $langs->trans("Discount") . ' 
' . $object->price_base_type . '  %
 ' . $object->price_base_type . ' ' . $object->price_base_type . '  %
' . $prices['quantity'] . '' . price($prices['price']) . '' . price($prices['unitprice']) . '' . price($prices['remise_percent']) . ' %'; @@ -1032,21 +1063,6 @@ else print '
 ' . $object->price_base_type . '  %
'; } else { print $langs->trans("No"); @@ -1071,7 +1087,8 @@ dol_fiche_end(); /* */ /* ************************************************************************** */ -if (! $action || $action == 'delete' || $action == 'showlog_customer_price' || $action == 'showlog_default_price' || $action == 'add_customer_price') +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";