BUG Fix of old hidden feature price per quantity

This commit is contained in:
Laurent Destailleur 2017-12-22 10:56:52 +01:00
parent d1cfbc2906
commit ff245aa646
6 changed files with 104 additions and 62 deletions

View File

@ -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;

View File

@ -17,6 +17,8 @@
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- 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;

View File

@ -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

View File

@ -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)) {

View File

@ -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

View File

@ -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 '<form action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="POST">';
print '<input type="hidden" name="action" value="update_price_by_qty">';
print '<input type="hidden" name="priceid" value="' . $object->prices_by_qty_id[$i] . '">';
print '<input type="hidden" value="0" name="rowid">';
print '<input type="hidden" name="priceid" value="' . $object->prices_by_qty_id[$i] . '">'; // id in product_price
print '<input type="hidden" value="0" name="rowid">'; // id in product_price
print '<tr class="' . ($ii % 2 == 0 ? 'pair' : 'impair') . '">';
print '<td><input size="5" type="text" value="1" name="quantity"></td>';
print '<td align="right" colspan="2"><input size="10" type="text" value="0" name="price">&nbsp;' . $object->price_base_type . '</td>';
@ -935,7 +940,7 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES))
print '</table>';
} else {
print $langs->trans("No");
print '&nbsp;<a href="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=activate_price_by_qty&level=' . $i . '">(' . $langs->trans("Activate") . ')</a>';
print '&nbsp; <a href="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=activate_price_by_qty&level=' . $i . '">(' . $langs->trans("Activate") . ')</a>';
}
print '</td></tr>';
}
@ -983,40 +988,66 @@ else
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) // TODO Fix the form inside tr instead of td
{
print '<tr><td>' . $langs->trans("PriceByQuantity");
if ($object->prices_by_qty [0] == 0) {
print '&nbsp;<a href="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=activate_price_by_qty&level=1">' . $langs->trans("Activate");
if ($object->prices_by_qty[0] == 0) {
print '&nbsp; <a href="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=activate_price_by_qty&level=1">(' . $langs->trans("Activate").')';
}
else
{
print '&nbsp; <a href="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&action=disable_price_by_qty&level=1">(' . $langs->trans("DisablePriceByQty").')';
}
print '</td><td>';
if ($object->prices_by_qty [0] == 1) {
if ($object->prices_by_qty [0] == 1)
{
print '<table width="50%" class="border" summary="List of quantities">';
print '<tr class="liste_titre">';
print '<td>' . $langs->trans("PriceByQuantityRange") . '</td>';
print '<td align="right">' . $langs->trans("HT") . '</td>';
//print '<td>' . $langs->trans("PriceByQuantityRange") . '</td>';
print '<td>' . $langs->trans("Quantity") . '</td>';
print '<td align="right">' . $langs->trans("Price") . '</td>';
print '<td align="right"></td>';
print '<td align="right">' . $langs->trans("UnitPrice") . '</td>';
print '<td align="right">' . $langs->trans("Discount") . '</td>';
print '<td>&nbsp;</td>';
print '</tr>';
foreach ($object->prices_by_qty_list [0] as $ii => $prices)
if ($action != 'edit_price_by_qty') {
print '<form action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="POST">'; // FIXME a form into a table is not allowed
print '<input type="hidden" name="action" value="update_price_by_qty">';
print '<input type="hidden" name="priceid" value="' . $object->prices_by_qty_id[0] . '">'; // id in product_price
print '<input type="hidden" value="0" name="rowid">'; // id in product_price_by_qty
print '<tr class="oddeven">';
print '<td><input size="5" type="text" value="1" name="quantity"></td>';
print '<td><input class="width50 right" type="text" value="0" name="price"></td>';
print '<td align="right">' . $object->price_base_type . '</td>';
print '<td align="right">&nbsp;</td>';
print '<td align="right"><input type="text" class="width50 right" value="0" name="remise_percent">&nbsp;%</td>';
print '<td align="center"><input type="submit" value="' . $langs->trans("Add") . '" class="button"></td>';
print '</tr>';
print '</form>';
}
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 '<form action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="POST">';
print '<input type="hidden" name="action" value="update_price_by_qty">';
print '<input type="hidden" name="priceid" value="' . $object->prices_by_qty_id[0] . '">';
print '<input type="hidden" value="' . $prices['rowid'] . '" name="rowid">';
print '<tr class="' . ($ii % 2 == 0 ? 'pair' : 'impair') . '">';
print '<input type="hidden" name="priceid" value="' . $object->prices_by_qty_id[0] . '">'; // id in product_price
print '<input type="hidden" value="' . $prices['rowid'] . '" name="rowid">'; // id in product_price_by_qty
print '<tr class="oddeven">';
print '<td><input size="5" type="text" value="' . $prices['quantity'] . '" name="quantity"></td>';
print '<td align="right" colspan="2"><input size="10" type="text" value="' . price2num($prices['price'], 'MU') . '" name="price">&nbsp;' . $object->price_base_type . '</td>';
// print '<td align="right">&nbsp;</td>';
print '<td align="right"><input size="10" type="text" value="' . price2num($prices['price'], 'MU') . '" name="price"></td>';
print '<td align="right">' . $object->price_base_type . '</td>';
print '<td align="right">&nbsp;</td>';
print '<td align="right"><input size="5" type="text" value="' . $prices['remise_percent'] . '" name="remise_percent">&nbsp;%</td>';
print '<td align="center"><input type="submit" value="' . $langs->trans("Modify") . '" class="button"></td>';
print '</tr>';
print '</form>';
} else {
print '<tr class="' . ($ii % 2 == 0 ? 'pair' : 'impair') . '">';
print '<tr class="oddeven">';
print '<td>' . $prices['quantity'] . '</td>';
print '<td align="right">' . price($prices['price']) . '</td>';
print '<td align="right"></td>';
print '<td align="right">' . price($prices['unitprice']) . '</td>';
print '<td align="right">' . price($prices['remise_percent']) . ' %</td>';
print '<td align="center">';
@ -1032,21 +1063,6 @@ else
print '</tr>';
}
}
if ($action != 'edit_price_by_qty') {
print '<form action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="POST">'; // FIXME a form into a table is not allowed
print '<input type="hidden" name="action" value="update_price_by_qty">';
print '<input type="hidden" name="priceid" value="' . $object->prices_by_qty_id [0] . '">';
print '<input type="hidden" value="0" name="rowid">';
print '<tr class="' . ($ii % 2 == 0 ? 'pair' : 'impair') . '">';
print '<td><input size="5" type="text" value="1" name="quantity"></td>';
print '<td align="right" colspan="2"><input size="10" type="text" value="0" name="price">&nbsp;' . $object->price_base_type . '</td>';
// print '<td align="right">&nbsp;</td>';
print '<td align="right"><input size="5" type="text" value="0" name="remise_percent">&nbsp;%</td>';
print '<td align="center"><input type="submit" value="' . $langs->trans("Add") . '" class="button"></td>';
print '</tr>';
print '</form>';
}
print '</table>';
} 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" . '<div class="tabsAction">' . "\n";