Merge pull request #1430 from FHenry/develop

Price management enhancement (multiprice level, price by …  customer, if MAIN_FEATURES_LEVEL=2 Price by qty)
This commit is contained in:
Laurent Destailleur 2014-02-24 10:14:48 +01:00
commit 28739414f2
24 changed files with 7863 additions and 6774 deletions

View File

@ -23,6 +23,8 @@ For users:
- New: Increase length of url into bookmark module.
- New: Add an admin page to make a mass init of barcode values for all products.
- New: Automatic events for sending mails showing info about mail linked objects.
- New: Price management enhancement (multiprice level, price by customer, if MAIN_FEATURES_LEVEL=2 Price by qty)
- Fix: Project Task numbering rule customs rule works
TODO
- New: Predefined product and free product use same form.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -105,8 +105,7 @@ if ($action == 'presend' && GETPOST('sendmail'))
$message = $conf->global->RELANCES_MASSE_TEXTE_EMAIL;
$subject = $conf->global->RELANCES_MASSE_OBJET_EMAIL;
$substitutionarray=
make_substitutions($message, $substitutionarray);
$substitutionarray=make_substitutions($message, $substitutionarray);
$actiontypecode='AC_FAC';
$actionmsg=$langs->transnoentities('MailSentBy').' '.$from.' '.$langs->transnoentities('To').' '.$sendto.".\n";

View File

@ -1264,9 +1264,10 @@ class Form
* @param string $selected_input_value Value of preselected input text (with ajax)
* @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after)
* @param array $ajaxoptions Options for ajax_autocompleter
* @param int $socid Thridparty Id
* @return void
*/
function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array())
function select_produits($selected='', $htmlname='productid', $filtertype='', $limit=20, $price_level=0, $status=1, $finished=2, $selected_input_value='', $hidelabel=0, $ajaxoptions=array(),$socid=0)
{
global $langs,$conf;
@ -1285,6 +1286,10 @@ class Form
}
// mode=1 means customers products
$urloption='htmlname='.$htmlname.'&outjson=1&price_level='.$price_level.'&type='.$filtertype.'&mode=1&status='.$status.'&finished='.$finished;
//Price by customer
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
$urloption.='&socid='.$socid;
}
print ajax_autocompleter($selected, $htmlname, DOL_URL_ROOT.'/product/ajax/products.php', $urloption, $conf->global->PRODUIT_USE_SEARCH_TO_SELECT, 0, $ajaxoptions);
if (empty($hidelabel)) print $langs->trans("RefOrLabel").' : ';
else if ($hidelabel > 1) {
@ -1301,7 +1306,7 @@ class Form
}
else
{
print $this->select_produits_list($selected,$htmlname,$filtertype,$limit,$price_level,'',$status,$finished,0);
print $this->select_produits_list($selected,$htmlname,$filtertype,$limit,$price_level,'',$status,$finished,0,$socid);
}
}
@ -1317,9 +1322,10 @@ class Form
* @param int $status -1=Return all products, 0=Products not on sell, 1=Products on sell
* @param int $finished Filter on finished field: 2=No filter
* @param int $outputmode 0=HTML select string, 1=Array
* @param int $socid Thridparty Id
* @return array Array of keys for json
*/
function select_produits_list($selected='',$htmlname='productid',$filtertype='',$limit=20,$price_level=0,$filterkey='',$status=1,$finished=2,$outputmode=0)
function select_produits_list($selected='',$htmlname='productid',$filtertype='',$limit=20,$price_level=0,$filterkey='',$status=1,$finished=2,$outputmode=0,$socid=0)
{
global $langs,$conf,$user,$db;
@ -1328,6 +1334,13 @@ class Form
$sql = "SELECT ";
$sql.= " p.rowid, p.label, p.ref, p.description, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.duration, p.stock";
//Price by customer
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
$sql.=' ,pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
$sql.=' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx';
}
// Multilang : we add translation
if (! empty($conf->global->MAIN_MULTILANGS))
{
@ -1337,15 +1350,19 @@ class Form
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
{
$sql.= ", (SELECT pp.rowid FROM ".MAIN_DB_PREFIX."product_price as pp WHERE pp.fk_product = p.rowid";
if ($price_level >= 1) $sql.= " AND price_level=".$price_level;
if ($price_level >= 1 && !empty($conf->global->PRODUIT_MULTIPRICES)) $sql.= " AND price_level=".$price_level;
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1) as price_rowid";
$sql.= ", (SELECT pp.price_by_qty FROM ".MAIN_DB_PREFIX."product_price as pp WHERE pp.fk_product = p.rowid";
if ($price_level >= 1) $sql.= " AND price_level=".$price_level;
if ($price_level >= 1 && !empty($conf->global->PRODUIT_MULTIPRICES)) $sql.= " AND price_level=".$price_level;
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1) as price_by_qty";
}
$sql.= " FROM ".MAIN_DB_PREFIX."product as p";
//Price by customer
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
$sql.=" LEFT JOIN ".MAIN_DB_PREFIX."product_customer_price as pcp ON pcp.fk_soc=".$socid." AND pcp.fk_product=p.rowid";
}
// Multilang : we add translation
if (! empty($conf->global->MAIN_MULTILANGS))
{
@ -1407,7 +1424,7 @@ class Form
$optJson = array();
$objp = $this->db->fetch_object($result);
if (!empty($objp->price_by_qty) && $objp->price_by_qty == 1)
if (!empty($objp->price_by_qty) && $objp->price_by_qty == 1 && !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
{ // Price by quantity will return many prices for the same product
$sql = "SELECT rowid, quantity, price, unitprice, remise_percent, remise";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty";
@ -1523,7 +1540,7 @@ class Form
$found=0;
// Multiprice
if ($price_level >= 1) // If we need a particular price level (from 1 to 6)
if ($price_level >= 1 && $conf->global->PRODUIT_MULTIPRICES) // If we need a particular price level (from 1 to 6)
{
$sql = "SELECT price, price_ttc, price_base_type, tva_tx";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price";
@ -1533,7 +1550,7 @@ class Form
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1";
dol_syslog(get_class($this)."::constructProductListOption search price for level '.$price_level.' sql=".$sql);
dol_syslog(get_class($this).'::constructProductListOption search price for level '.$price_level.' sql='.$sql);
$result2 = $this->db->query($sql);
if ($result2)
{
@ -1564,7 +1581,7 @@ class Form
}
// Price by quantity
if (!empty($objp->quantity) && $objp->quantity >= 1)
if (!empty($objp->quantity) && $objp->quantity >= 1 && $conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)
{
$found = 1;
$outqty=$objp->quantity;
@ -1599,6 +1616,29 @@ class Form
$opt.=" - ".$langs->trans("Discount")." : ".vatrate($objp->remise_percent).' %';
$outval.=" - ".$langs->transnoentities("Discount")." : ".vatrate($objp->remise_percent).' %';
}
//Price by customer
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
if (!empty($objp->idprodcustprice)) {
$found = 1;
if ($objp->custprice_base_type == 'HT')
{
$opt.= price($objp->custprice,1).' '.$currencytext.' '.$langs->trans("HT");
$outval.= price($objp->custprice,1).' '.$currencytextnoent.' '.$langs->transnoentities("HT");
}
else
{
$opt.= price($objp->custprice_ttc,1).' '.$currencytext.' '.$langs->trans("TTC");
$outval.= price($objp->custprice_ttc,1).' '.$currencytextnoent.' '.$langs->transnoentities("TTC");
}
$outprice_ht=price($objp->custprice);
$outprice_ttc=price($objp->custprice_ttc);
$outpricebasetype=$objp->custprice_base_type;
$outtva_tx=$objp->custtva_tx;
}
}
// If level no defined or multiprice not found, we used the default price
if (! $found)
@ -3735,7 +3775,7 @@ class Form
*
* @param string $htmlname Name of html select area
* @param array $array Array with key+value
* @param int $id Preselected key
* @param string $id Preselected key
* @param int $show_empty 1 si il faut ajouter une valeur vide dans la liste, 0 sinon
* @param int $key_in_label 1 pour afficher la key dans la valeur "[key] value"
* @param int $value_as_key 1 to use value as key

View File

@ -3,7 +3,7 @@
* Copyright (C) 2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
* Copyright (C) 2010-2012 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2013 Christophe Battarel <contact@altairis.fr>
* Copyright (C) 2013 Alexandre Spangaro <alexandre.spangaro@gmail.com>
@ -136,6 +136,16 @@ function societe_prepare_head($object)
$h++;
}
if (($object->client==1 || $object->client==2 || $object->client==3) && (! empty ( $conf->global->PRODUIT_CUSTOMER_PRICES )))
{
$langs->load("products");
// price
$head[$h][0] = DOL_URL_ROOT.'/societe/price.php?socid='.$object->id;
$head[$h][1] = $langs->trans("CustomerPrices");
$head[$h][2] = 'price';
$h++;
}
// Log
$head[$h][0] = DOL_URL_ROOT.'/societe/info.php?socid='.$object->id;
$head[$h][1] = $langs->trans("Info");

View File

@ -2868,7 +2868,7 @@ function get_localtax($tva, $local, $thirdparty_buyer="", $thirdparty_seller="")
global $db, $conf, $mysoc;
if (empty($thirdparty_seller) || ! is_object($thirdparty_seller)) $thirdparty_seller=$mysoc;
dol_syslog("get_localtax tva=".$tva." local=".$local." thirdparty_buyer id=".(is_object($thirdparty_buyer)?$thirdparty_buyer->id:'')."/country_code=".(is_object($thirdparty_buyer)?$thirdparty_buyer->country_code:'')." thirdparty_seller id=".$thirdparty_seller->id."/country_code=".$thirdparty_seller->country_code." thirdparty_seller localtax1_assuj=".$thirdparty_seller->localtax1_assuj." thirdparty_seller localtax2_assuj=".$thirdparty_seller->localtax2_assuj);
// Some test to guess with no need to make database access

View File

@ -270,7 +270,7 @@ class modSociete extends DolibarrModules
$this->export_TypeFields_array[$r]=array('s.nom'=>"Text",'s.status'=>"Number",'s.client'=>"Boolean",'s.fournisseur'=>"Boolean",'s.datec'=>"Date",'s.tms'=>"Date",'s.code_client'=>"Text",'s.code_fournisseur'=>"Text",'s.code_compta'=>"Text",'s.code_compta_fournisseur'=>"Text",'s.address'=>"Text",'s.zip'=>"Text",'s.town'=>"Text",'p.libelle'=>"List:c_pays:libelle:libelle",'p.code'=>"Text",'s.phone'=>"Text",'s.fax'=>"Text",'s.url'=>"Text",'s.email'=>"Text",'s.default_lang'=>"Text",'s.siret'=>"Text",'s.siren'=>"Text",'s.ape'=>"Text",'s.idprof4'=>"Text",'s.idprof5'=>"Text",'s.idprof6'=>"Text",'s.tva_intra'=>"Text",'s.capital'=>"Number",'s.note_private'=>"Text",'s.note_public'=>"Text",'t.libelle'=>"Text",'ce.code'=>"List:c_effectif:libelle:code","cfj.libelle"=>"Text",'s.fk_prospectlevel'=>'List:c_prospectlevel:label:code','st.code'=>'List:c_stcomm:libelle:code','d.nom'=>'Text');
$this->export_entities_array[$r]=array(); // We define here only fields that use another picto
// Add extra fields
$sql="SELECT name, label, type FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'societe'";
$sql="SELECT name, label, type, param FROM ".MAIN_DB_PREFIX."extrafields WHERE elementtype = 'societe'";
$resql=$this->db->query($sql);
if ($resql) // This can fail when class is used on old database (during migration for example)
{

View File

@ -107,7 +107,7 @@ if (! empty($conf->margin->enabled)) {
'select_type'
)
);
$form->select_produits('', 'idprod', '', $conf->product->limit_size, $buyer->price_level, 1, 2, '', 3, $ajaxoptions);
$form->select_produits('', 'idprod', '', $conf->product->limit_size, $buyer->price_level, 1, 2, '', 3, $ajaxoptions,$buyer->id);
}
?>
<span id="add_product_area" class="hideobject"> | <input type="checkbox" id="add_product_checkbox" name="add_product" value="1" />
@ -270,6 +270,9 @@ $(document).ready(function() {
'id': $(this).val(),
'price_level': <?php echo empty($buyer->price_level)?1:$buyer->price_level; ?>,
'pbq': $("option:selected", this).attr('pbq')
<?php if (! empty ( $conf->global->PRODUIT_CUSTOMER_PRICES )) {?>
,'socid': <?php echo $buyer->id; ?>
<?php }?>
},
function(data) {
if (typeof data != 'undefined') {

View File

@ -101,7 +101,7 @@ else {
echo '<span>';
$filtertype='';
if (! empty($object->element) && $object->element == 'contrat') $filtertype='1';
$form->select_produits('','idprod',$filtertype,$conf->product->limit_size,$buyer->price_level);
$form->select_produits('','idprod',$filtertype,$conf->product->limit_size,$buyer->price_level, 1, 2, '', 3, array(),$buyer->id);
echo '</span>';
if (is_object($hookmanager))

View File

@ -957,3 +957,56 @@ INSERT INTO llx_accountingaccount (fk_pcg_version, pcg_type, pcg_subtype, accoun
INSERT INTO llx_accountingaccount (fk_pcg_version, pcg_type, pcg_subtype, account_number, account_parent, label, active) VALUE ('PCMN-BASE', 'PROD', 'XXXXXX', '793', '79', 'Perte à reporter', '1');
INSERT INTO llx_accountingaccount (fk_pcg_version, pcg_type, pcg_subtype, account_number, account_parent, label, active) VALUE ('PCMN-BASE', 'PROD', 'XXXXXX', '794', '79', 'Intervention d''associés (ou du propriétaire) dans la perte', '1');
ALTER TABLE llx_projet_task ADD COLUMN entity integer DEFAULT 1 NOT NULL AFTER ref;
create table llx_product_customer_price
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 1 NOT NULL, -- multi company id
datec datetime,
tms timestamp,
fk_product integer NOT NULL,
fk_soc integer NOT NULL,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
price_min_ttc double(24,8) DEFAULT 0,
price_base_type varchar(3) DEFAULT 'HT',
tva_tx double(6,3),
recuperableonly integer NOT NULL DEFAULT '0', -- Other NPR VAT
localtax1_tx double(6,3) DEFAULT 0, -- Other local VAT 1
localtax2_tx double(6,3) DEFAULT 0, -- Other local VAT 2
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;
ALTER TABLE llx_product_customer_price ADD INDEX idx_product_customer_price_fk_user (fk_user);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_product_customer_price_fk_user FOREIGN KEY (fk_user) REFERENCES llx_user (rowid);
ALTER TABLE llx_product_customer_price ADD UNIQUE INDEX uk_customer_price_fk_product_fk_soc (fk_product, fk_soc);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_customer_price_fk_product FOREIGN KEY (fk_product) REFERENCES llx_product(rowid) ON DELETE CASCADE;
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_customer_price_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid) ON DELETE CASCADE;
create table llx_product_customer_price_log
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 1 NOT NULL, -- multi company id
datec datetime,
fk_product integer NOT NULL,
fk_soc integer NOT NULL,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
price_min_ttc double(24,8) DEFAULT 0,
price_base_type varchar(3) DEFAULT 'HT',
tva_tx double(6,3),
recuperableonly integer NOT NULL DEFAULT '0', -- Other NPR VAT
localtax1_tx double(6,3) DEFAULT 0, -- Other local VAT 1
localtax2_tx double(6,3) DEFAULT 0, -- Other local VAT 2
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;

View File

@ -0,0 +1,30 @@
-- ============================================================================
-- Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2005-2012 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2009-2012 Regis Houssin <regis.houssin@capnetworks.com>
-- Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
--
-- 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 <http://www.gnu.org/licenses/>.
--
-- ============================================================================
ALTER TABLE llx_product_customer_price ADD INDEX idx_product_customer_price_fk_user (fk_user);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_product_customer_price_fk_user FOREIGN KEY (fk_user) REFERENCES llx_user (rowid);
ALTER TABLE llx_product_customer_price ADD UNIQUE INDEX uk_customer_price_fk_product_fk_soc (fk_product, fk_soc);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_customer_price_fk_product FOREIGN KEY (fk_product) REFERENCES llx_product(rowid) ON DELETE CASCADE;
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_customer_price_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid) ON DELETE CASCADE;

View File

@ -0,0 +1,42 @@
-- ============================================================================
-- Copyright (C) 2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2009-2011 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2009-2013 Regis Houssin <regis.houssin@capnetworks.com>
-- Copyright (C) 2012 Juanjo Menent <jmenent@2byte.es>
-- Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
--
-- 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 <http://www.gnu.org/licenses/>.
--
-- ============================================================================
create table llx_product_customer_price
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 1 NOT NULL, -- multi company id
datec datetime,
tms timestamp,
fk_product integer NOT NULL,
fk_soc integer NOT NULL,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
price_min_ttc double(24,8) DEFAULT 0,
price_base_type varchar(3) DEFAULT 'HT',
tva_tx double(6,3),
recuperableonly integer NOT NULL DEFAULT '0', -- Other NPR VAT
localtax1_tx double(6,3) DEFAULT 0, -- Other local VAT 1
localtax2_tx double(6,3) DEFAULT 0, -- Other local VAT 2
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;

View File

@ -0,0 +1,39 @@
-- ============================================================================
-- Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2009 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
--
-- 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 <http://www.gnu.org/licenses/>.
--
-- ============================================================================
create table llx_product_customer_price_log
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
entity integer DEFAULT 1 NOT NULL, -- multi company id
datec datetime,
fk_product integer NOT NULL,
fk_soc integer NOT NULL,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
price_min_ttc double(24,8) DEFAULT 0,
price_base_type varchar(3) DEFAULT 'HT',
tva_tx double(6,3),
recuperableonly integer NOT NULL DEFAULT '0', -- Other NPR VAT
localtax1_tx double(6,3) DEFAULT 0, -- Other local VAT 1
localtax2_tx double(6,3) DEFAULT 0, -- Other local VAT 2
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;

View File

@ -21,6 +21,7 @@ create table llx_projet_task
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
ref varchar(50),
entity integer DEFAULT 1 NOT NULL, -- multi company id
fk_projet integer NOT NULL,
fk_task_parent integer DEFAULT 0 NOT NULL,
datec datetime, -- date creation

View File

@ -221,3 +221,9 @@ DefinitionOfBarCodeForThirdpartyNotComplete=Definition of type or value of bar c
BarCodeDataForProduct=Barcode information of product %s :
BarCodeDataForThirdparty=Barcode information of thirdparty %s :
ResetBarcodeForAllRecords=Define barcode value for all records (this will also reset barcode value already defined with new values)
PriceByCustomer=Price by customer
PriceCatalogue=Catalogue Price
PricingRule=Pricing Rules
AddCustomerPrice=Add price by customers
ForceUpdateChildPriceSoc=Set same price on customer subsidiaries
PriceByCustomerLog=Price by customer log

View File

@ -217,4 +217,9 @@ DefinitionOfBarCodeForThirdpartyNotComplete=Définition du type ou valeure du co
BarCodeDataForProduct=Information de code barre du produit %s :
BarCodeDataForThirdparty=Information de code barre du tiers %s :
BarcodeStickersMask=xxx
PriceByCustomer=Prix par clients
PriceCatalogue=Prix unique
PricingRule=Régles de prix
AddCustomerPrice=Ajouter un prix par client
ForceUpdateChildPriceSoc=Mettre le même prix pour les filliales
PriceByCustomerLog=Historique prix par client

View File

@ -42,6 +42,17 @@ if (! $user->admin || (empty($conf->product->enabled) && empty($conf->service->e
$action = GETPOST('action','alpha');
$value = GETPOST('value','alpha');
// Pricing Rules
$select_pricing_rules=array(
'PRODUCT_PRICE_UNIQ'=>$langs->trans('PriceCatalogue'),
'PRODUIT_MULTIPRICES'=>$langs->trans('MultiPricesAbility'),
'PRODUIT_CUSTOMER_PRICES'=>$langs->trans('PriceByCustomer')
);
if ($conf->global->MAIN_FEATURES_LEVEL==2) {
$select_pricing_rules['PRODUIT_CUSTOMER_PRICES_BY_QTY'] = $langs->trans('PriceByQuantity');
$select_pricing_rules['PRODUIT_CUSTOMER_PRICES_BY_QTY&PRODUIT_MULTIPRICES'] = $langs->trans('MultiPricesAbility') . '+' . $langs->trans('PriceByQuantity');
}
/*
* Actions
@ -96,12 +107,33 @@ else if ($action == 'multiprix_num')
{
$res = dolibarr_set_const($db, "PRODUIT_MULTIPRICES_LIMIT", $value,'chaine',0,'',$conf->entity);
}
if ($action == 'multiprix')
if ($action == 'pricingrule')
{
$multiprix = GETPOST('activate_multiprix','alpha');
$princingrules = GETPOST('princingrule','alpha');
foreach ($select_pricing_rules as $rule=>$label) {
$res = dolibarr_set_const($db, "PRODUIT_MULTIPRICES", $multiprix,'chaine',0,'',$conf->entity);
$res =dolibarr_set_const($db, "PRODUIT_MULTIPRICES_LIMIT", "5",'chaine',0,'',$conf->entity);
if ($rule==$princingrules) {
if ( $princingrules =='PRODUCT_PRICE_UNIQ') {
$res = dolibarr_set_const($db, 'PRODUIT_MULTIPRICES', 0,'chaine',0,'',$conf->entity);
$res = dolibarr_set_const($db, 'PRODUIT_CUSTOMER_PRICES_BY_QTY', 0,'chaine',0,'',$conf->entity);
$res = dolibarr_set_const($db, 'PRODUIT_CUSTOMER_PRICES', 0,'chaine',0,'',$conf->entity);
} else {
$multirule=explode('&',$princingrules);
if (is_array($multirule) && count($multirule)>0) {
foreach($multirule as $rulesselected) {
$res = dolibarr_set_const($db, $rulesselected, 1,'chaine',0,'',$conf->entity);
}
} else {
$res = dolibarr_set_const($db, $rule, 1,'chaine',0,'',$conf->entity);
}
}
} else {
if (strpos($rule,'&')===false) {
$res = dolibarr_set_const($db, $rule, 0,'chaine',0,'',$conf->entity);
}
}
}
}
else if ($action == 'sousproduits')
{
@ -278,15 +310,20 @@ print '<td width="80">&nbsp;</td></tr>'."\n";
* Formulaire parametres divers
*/
// multiprix activation/desactivation
$var=!$var;
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="multiprix">';
print '<input type="hidden" name="action" value="pricingrule">';
print '<tr '.$bc[$var].'>';
print '<td>'.$langs->trans("MultiPricesAbility").'</td>';
print '<td>'.$langs->trans("PricingRule").'</td>';
print '<td width="60" align="right">';
print $form->selectyesno("activate_multiprix",$conf->global->PRODUIT_MULTIPRICES,1);
$current_rule = 'PRODUCT_PRICE_UNIQ';
if (!empty($conf->global->PRODUIT_MULTIPRICES)) $current_rule='PRODUIT_MULTIPRICES';
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) $current_rule='PRODUIT_CUSTOMER_PRICES_BY_QTY';
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES)) $current_rule='PRODUIT_CUSTOMER_PRICES';
if ((!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) && (!empty($conf->global->PRODUIT_MULTIPRICES)))$current_rule='PRODUIT_CUSTOMER_PRICES_BY_QTY&PRODUIT_MULTIPRICES';
print $form->selectarray("princingrule",$select_pricing_rules,$current_rule);
print '</td><td align="right">';
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print '</td>';

View File

@ -18,156 +18,176 @@
*/
/**
* \file htdocs/product/ajax/products.php
* \brief File to return Ajax response on product list request
* \file htdocs/product/ajax/products.php
* \brief File to return Ajax response on product list request
*/
if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL',1); // Disables token renewal
if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1');
if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1');
if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1');
if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1');
if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1');
if (empty($_GET['keysearch']) && ! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1');
if (! defined('NOTOKENRENEWAL'))
define('NOTOKENRENEWAL', 1); // Disables token renewal
if (! defined('NOREQUIREMENU'))
define('NOREQUIREMENU', '1');
if (! defined('NOREQUIREHTML'))
define('NOREQUIREHTML', '1');
if (! defined('NOREQUIREAJAX'))
define('NOREQUIREAJAX', '1');
if (! defined('NOREQUIRESOC'))
define('NOREQUIRESOC', '1');
if (! defined('NOCSRFCHECK'))
define('NOCSRFCHECK', '1');
if (empty($_GET ['keysearch']) && ! defined('NOREQUIREHTML'))
define('NOREQUIREHTML', '1');
require '../../main.inc.php';
$htmlname=GETPOST('htmlname','alpha');
$socid=GETPOST('socid','int');
$type=GETPOST('type','int');
$mode=GETPOST('mode','int');
$status=((GETPOST('status','int') >= 0) ? GETPOST('status','int') : -1);
$outjson=(GETPOST('outjson','int') ? GETPOST('outjson','int') : 0);
$price_level=GETPOST('price_level','int');
$action=GETPOST('action', 'alpha');
$id=GETPOST('id', 'int');
$price_by_qty_rowid=GETPOST('pbq', 'int');
$htmlname = GETPOST('htmlname', 'alpha');
$socid = GETPOST('socid', 'int');
$type = GETPOST('type', 'int');
$mode = GETPOST('mode', 'int');
$status = ((GETPOST('status', 'int') >= 0) ? GETPOST('status', 'int') : - 1);
$outjson = (GETPOST('outjson', 'int') ? GETPOST('outjson', 'int') : 0);
$price_level = GETPOST('price_level', 'int');
$action = GETPOST('action', 'alpha');
$id = GETPOST('id', 'int');
$price_by_qty_rowid = GETPOST('pbq', 'int');
/*
* View
*/
//print '<!-- Ajax page called with url '.$_SERVER["PHP_SELF"].'?'.$_SERVER["QUERY_STRING"].' -->'."\n";
// print '<!-- Ajax page called with url '.$_SERVER["PHP_SELF"].'?'.$_SERVER["QUERY_STRING"].' -->'."\n";
dol_syslog(join(',',$_GET));
//print_r($_GET);
dol_syslog(join(',', $_GET));
// print_r($_GET);
if (! empty($action) && $action == 'fetch' && ! empty($id))
{
if (! empty($action) && $action == 'fetch' && ! empty($id)) {
require DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
$outjson=array();
$outjson = array();
$object = new Product($db);
$ret=$object->fetch($id);
if ($ret > 0)
{
$outref=$object->ref;
$outlabel=$object->label;
$outdesc=$object->description;
$outtype=$object->type;
$outqty=1;
$outdiscount=0;
$found=false;
$ret = $object->fetch($id);
if ($ret > 0) {
$outref = $object->ref;
$outlabel = $object->label;
$outdesc = $object->description;
$outtype = $object->type;
$outqty = 1;
$outdiscount = 0;
$found = false;
// Price by qty
if (!empty($price_by_qty_rowid) && $price_by_qty_rowid >= 1) // If we need a particular price related to qty
if (! empty($price_by_qty_rowid) && $price_by_qty_rowid >= 1 && (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))) // If we need a
// particular price related
// to qty
{
$sql = "SELECT price, unitprice, quantity, remise_percent";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty ";
$sql.= " WHERE rowid=".$price_by_qty_rowid."";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_price_by_qty ";
$sql .= " WHERE rowid=" . $price_by_qty_rowid . "";
$result = $db->query($sql);
if ($result)
{
if ($result) {
$objp = $db->fetch_object($result);
if ($objp)
{
$found=true;
$outprice_ht=price($objp->unitprice);
$outprice_ttc=price($objp->unitprice * (1 + ($object->tva_tx / 100)));
$outpricebasetype=$object->price_base_type;
$outtva_tx=$object->tva_tx;
$outqty=$objp->quantity;
$outdiscount=$objp->remise_percent;
if ($objp) {
$found = true;
$outprice_ht = price($objp->unitprice);
$outprice_ttc = price($objp->unitprice * (1 + ($object->tva_tx / 100)));
$outpricebasetype = $object->price_base_type;
$outtva_tx = $object->tva_tx;
$outqty = $objp->quantity;
$outdiscount = $objp->remise_percent;
}
}
}
// Multiprice
if (! $found && isset($price_level) && $price_level >= 1) // If we need a particular price level (from 1 to 6)
if (! $found && isset($price_level) && $price_level >= 1 && (! empty($conf->global->PRODUIT_MULTIPRICES))) // If we need a particular price
// level (from 1 to 6)
{
$sql = "SELECT price, price_ttc, price_base_type, tva_tx";
$sql.= " FROM ".MAIN_DB_PREFIX."product_price ";
$sql.= " WHERE fk_product='".$id."'";
$sql.= " AND entity IN (".getEntity('productprice', 1).")";
$sql.= " AND price_level=".$price_level;
$sql.= " ORDER BY date_price";
$sql.= " DESC LIMIT 1";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_price ";
$sql .= " WHERE fk_product='" . $id . "'";
$sql .= " AND entity IN (" . getEntity('productprice', 1) . ")";
$sql .= " AND price_level=" . $price_level;
$sql .= " ORDER BY date_price";
$sql .= " DESC LIMIT 1";
$result = $db->query($sql);
if ($result)
{
if ($result) {
$objp = $db->fetch_object($result);
if ($objp)
{
$found=true;
$outprice_ht=price($objp->price);
$outprice_ttc=price($objp->price_ttc);
$outpricebasetype=$objp->price_base_type;
$outtva_tx=$objp->tva_tx;
if ($objp) {
$found = true;
$outprice_ht = price($objp->price);
$outprice_ttc = price($objp->price_ttc);
$outpricebasetype = $objp->price_base_type;
$outtva_tx = $objp->tva_tx;
}
}
}
if (! $found)
{
$outprice_ht=price($object->price);
$outprice_ttc=price($object->price_ttc);
$outpricebasetype=$object->price_base_type;
$outtva_tx=$object->tva_tx;
// Price by customer
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES) && ! empty($socid)) {
require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
$prodcustprice = new Productcustomerprice($db);
$filter = array('t.fk_product' => $object->id,'t.fk_soc' => $socid);
$result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
if ($result) {
if (count($prodcustprice->lines) > 0) {
$found = true;
$outprice_ht = price($prodcustprice->lines [0]->price);
$outprice_ttc = price($prodcustprice->lines [0]->price_ttc);
$outpricebasetype = $prodcustprice->lines [0]->price_base_type;
$outtva_tx = $prodcustprice->lines [0]->tva_tx;
}
}
}
$outjson = array('ref'=>$outref, 'label'=>$outlabel, 'desc'=>$outdesc, 'type'=>$outtype, 'price_ht'=>$outprice_ht, 'price_ttc'=>$outprice_ttc, 'pricebasetype'=>$outpricebasetype, 'tva_tx'=>$outtva_tx, 'qty'=>$outqty, 'discount'=>$outdiscount);
if (! $found) {
$outprice_ht = price($object->price);
$outprice_ttc = price($object->price_ttc);
$outpricebasetype = $object->price_base_type;
$outtva_tx = $object->tva_tx;
}
$outjson = array('ref' => $outref,'label' => $outlabel,'desc' => $outdesc,'type' => $outtype,'price_ht' => $outprice_ht,'price_ttc' => $outprice_ttc,'pricebasetype' => $outpricebasetype,'tva_tx' => $outtva_tx,'qty' => $outqty,'discount' => $outdiscount);
}
echo json_encode($outjson);
}
else
{
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
} else {
require_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php';
$langs->load("products");
$langs->load("main");
top_httphead();
if (empty($htmlname)) return;
$match = preg_grep('/('.$htmlname.'[0-9]+)/',array_keys($_GET));
if (empty($htmlname))
return;
$match = preg_grep('/(' . $htmlname . '[0-9]+)/', array_keys($_GET));
sort($match);
$idprod = (! empty($match[0]) ? $match[0] : '');
if (! GETPOST($htmlname) && ! GETPOST($idprod)) return;
// When used from jQuery, the search term is added as GET param "term".
$searchkey=(GETPOST($idprod)?GETPOST($idprod):(GETPOST($htmlname)?GETPOST($htmlname):''));
$idprod = (! empty($match [0]) ? $match [0] : '');
if (! GETPOST($htmlname) && ! GETPOST($idprod))
return;
// When used from jQuery, the search term is added as GET param "term".
$searchkey = (GETPOST($idprod) ? GETPOST($idprod) : (GETPOST($htmlname) ? GETPOST($htmlname) : ''));
$form = new Form($db);
if (empty($mode) || $mode == 1)
{
$arrayresult=$form->select_produits_list("",$htmlname,$type,"",$price_level,$searchkey,$status,2,$outjson);
if (empty($mode) || $mode == 1) {
$arrayresult = $form->select_produits_list("", $htmlname, $type, "", $price_level, $searchkey, $status, 2, $outjson, $socid);
} elseif ($mode == 2) {
$arrayresult = $form->select_produits_fournisseurs_list($socid, "", $htmlname, $type, "", $searchkey, $status, $outjson, $socid);
}
elseif ($mode == 2)
{
$arrayresult=$form->select_produits_fournisseurs_list($socid,"",$htmlname,$type,"",$searchkey,$status,$outjson);
}
$db->close();
if ($outjson) print json_encode($arrayresult);
if ($outjson)
print json_encode($arrayresult);
}
?>

View File

@ -1183,6 +1183,7 @@ class Product extends CommonObject
}
//print 'x'.$id.'-'.$newprice.'-'.$newpricebase.'-'.$price.'-'.$price_ttc.'-'.$price_min.'-'.$price_min_ttc;
//Local taxes
$localtax1=get_localtax($newvat,1);
$localtax2=get_localtax($newvat,2);

View File

@ -0,0 +1,946 @@
<?php
/* Copyright (C) 2007-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/product/class/productcustomerprice.class.php
* \ingroup produit
* \brief File of class to manage predefined price products or services by customer
*/
require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php';
/**
* File of class to manage predefined price products or services by customer
*/
class Productcustomerprice extends CommonObject
{
var $db; // !< To store db handler
var $error; // !< To return error code (or message)
var $errors = array (); // !< To return several error codes (or messages)
var $element = 'product_customer_price'; // !< Id that identify managed objects
var $table_element = 'product_customer_price'; // !< Name of table without prefix where object is stored
var $id;
var $entity;
var $datec = '';
var $tms = '';
var $fk_product;
var $fk_soc;
var $price;
var $price_ttc;
var $price_min;
var $price_min_ttc;
var $price_base_type;
var $tva_tx;
var $recuperableonly;
var $localtax1_tx;
var $localtax2_tx;
var $fk_user;
var $import_key;
var $lines = array ();
/**
* Constructor
*
* @param DoliDb $db handler
*/
function __construct($db) {
$this->db = $db;
return 1;
}
/**
* Create object into database
*
* @param User $user that creates
* @param int $notrigger triggers after, 1=disable triggers
* @param int $forceupdateaffiliate update price on each soc child
* @return int <0 if KO, Id of created object if OK
*/
function create($user, $notrigger = 0, $forceupdateaffiliate = 0) {
global $conf, $langs;
$error = 0;
// Clean parameters
if (isset($this->entity))
$this->entity = trim($this->entity);
if (isset($this->fk_product))
$this->fk_product = trim($this->fk_product);
if (isset($this->fk_soc))
$this->fk_soc = trim($this->fk_soc);
if (isset($this->price))
$this->price = trim($this->price);
if (isset($this->price_ttc))
$this->price_ttc = trim($this->price_ttc);
if (isset($this->price_min))
$this->price_min = trim($this->price_min);
if (isset($this->price_min_ttc))
$this->price_min_ttc = trim($this->price_min_ttc);
if (isset($this->price_base_type))
$this->price_base_type = trim($this->price_base_type);
if (isset($this->tva_tx))
$this->tva_tx = trim($this->tva_tx);
if (isset($this->recuperableonly))
$this->recuperableonly = trim($this->recuperableonly);
if (isset($this->localtax1_tx))
$this->localtax1_tx = trim($this->localtax1_tx);
if (isset($this->localtax2_tx))
$this->localtax2_tx = trim($this->localtax2_tx);
if (isset($this->fk_user))
$this->fk_user = trim($this->fk_user);
if (isset($this->import_key))
$this->import_key = trim($this->import_key);
// Check parameters
// Put here code to add control on parameters values
if ($this->price != '' || $this->price == 0) {
if ($this->price_base_type == 'TTC') {
$this->price_ttc = price2num($this->price, 'MU');
$this->price = price2num($this->price) / (1 + ($this->tva_tx / 100));
$this->price = price2num($this->price, 'MU');
if ($this->price_min != '' || $this->price_min == 0) {
$this->price_min_ttc = price2num($this->price_min, 'MU');
$this->price_min = price2num($this->price_min) / (1 + ($this->tva_tx / 100));
$this->price_min = price2num($this->price_min, 'MU');
} else {
$this->price_min = 0;
$this->price_min_ttc = 0;
}
} else {
$this->price = price2num($this->price, 'MU');
$this->price_ttc = ($this->recuperableonly != 1) ? price2num($this->price) * (1 + ($this->tva_tx / 100)) : $this->price;
$this->price_ttc = price2num($this->price_ttc, 'MU');
if ($this->price_min != '' || $this->price_min == 0) {
$this->price_min = price2num($this->price_min, 'MU');
$this->price_min_ttc = price2num($this->price_min) * (1 + ($this->tva_tx / 100));
$this->price_min_ttc = price2num($this->price_min_ttc, 'MU');
// print 'X'.$newminprice.'-'.$price_min;
} else {
$this->price_min = 0;
$this->price_min_ttc = 0;
}
}
}
// Insert request
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_customer_price(";
$sql .= "entity,";
$sql .= "datec,";
$sql .= "fk_product,";
$sql .= "fk_soc,";
$sql .= "price,";
$sql .= "price_ttc,";
$sql .= "price_min,";
$sql .= "price_min_ttc,";
$sql .= "price_base_type,";
$sql .= "tva_tx,";
$sql .= "recuperableonly,";
$sql .= "localtax1_tx,";
$sql .= "localtax2_tx,";
$sql .= "fk_user,";
$sql .= "import_key";
$sql .= ") VALUES (";
$sql .= " " . $conf->entity . ",";
$sql .= " '" . $this->db->idate(dol_now()) . "',";
$sql .= " " . (! isset($this->fk_product) ? 'NULL' : "'" . $this->fk_product . "'") . ",";
$sql .= " " . (! isset($this->fk_soc) ? 'NULL' : "'" . $this->fk_soc . "'") . ",";
$sql .= " " . (empty($this->price) ? '0' : "'" . $this->price . "'") . ",";
$sql .= " " . (empty($this->price_ttc) ? '0' : "'" . $this->price_ttc . "'") . ",";
$sql .= " " . (empty($this->price_min) ? '0' : "'" . $this->price_min . "'") . ",";
$sql .= " " . (empty($this->price_min_ttc) ? '0' : "'" . $this->price_min_ttc . "'") . ",";
$sql .= " " . (! isset($this->price_base_type) ? 'NULL' : "'" . $this->db->escape($this->price_base_type) . "'") . ",";
$sql .= " " . (! isset($this->tva_tx) ? 'NULL' : "'" . $this->tva_tx . "'") . ",";
$sql .= " " . (! isset($this->recuperableonly) ? 'NULL' : "'" . $this->recuperableonly . "'") . ",";
$sql .= " " . (! isset($this->localtax1_tx) ? 'NULL' : "'" . $this->localtax1_tx . "'") . ",";
$sql .= " " . (! isset($this->localtax2_tx) ? 'NULL' : "'" . $this->localtax2_tx . "'") . ",";
$sql .= " " . $user->id . ",";
$sql .= " " . (! isset($this->import_key) ? 'NULL' : "'" . $this->db->escape($this->import_key) . "'") . "";
$sql .= ")";
$this->db->begin();
dol_syslog(get_class($this) . "::create sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if (! $resql) {
$error ++;
$this->errors [] = "Error " . $this->db->lasterror();
}
if (! $error) {
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . "product_customer_price");
if (! $notrigger) {
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
// // Call triggers
// include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
// $interface=new Interfaces($this->db);
// $result=$interface->run_triggers('MYOBJECT_CREATE',$this,$user,$langs,$conf);
// if ($result < 0) { $error++; $this->errors=$interface->errors; }
// // End call triggers
}
}
if (! $error) {
$result = $this->setPriceOnAffiliateThirdparty($user, $forceupdateaffiliate);
if ($result < 0) {
$error ++;
}
}
// Commit or rollback
if ($error) {
foreach ( $this->errors as $errmsg ) {
dol_syslog(get_class($this) . "::create " . $errmsg, LOG_ERR);
$this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
}
$this->db->rollback();
return - 1 * $error;
} else {
$this->db->commit();
return $this->id;
}
}
/**
* Load object in memory from the database
*
* @param int $id object
* @return int <0 if KO, >0 if OK
*/
function fetch($id) {
global $langs;
$sql = "SELECT";
$sql .= " t.rowid,";
$sql .= " t.entity,";
$sql .= " t.datec,";
$sql .= " t.tms,";
$sql .= " t.fk_product,";
$sql .= " t.fk_soc,";
$sql .= " t.price,";
$sql .= " t.price_ttc,";
$sql .= " t.price_min,";
$sql .= " t.price_min_ttc,";
$sql .= " t.price_base_type,";
$sql .= " t.tva_tx,";
$sql .= " t.recuperableonly,";
$sql .= " t.localtax1_tx,";
$sql .= " t.localtax2_tx,";
$sql .= " t.fk_user,";
$sql .= " t.import_key";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_customer_price as t";
$sql .= " WHERE t.rowid = " . $id;
dol_syslog(get_class($this) . "::fetch sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
if ($this->db->num_rows($resql)) {
$obj = $this->db->fetch_object($resql);
$this->id = $obj->rowid;
$this->entity = $obj->entity;
$this->datec = $this->db->jdate($obj->datec);
$this->tms = $this->db->jdate($obj->tms);
$this->fk_product = $obj->fk_product;
$this->fk_soc = $obj->fk_soc;
$this->price = $obj->price;
$this->price_ttc = $obj->price_ttc;
$this->price_min = $obj->price_min;
$this->price_min_ttc = $obj->price_min_ttc;
$this->price_base_type = $obj->price_base_type;
$this->tva_tx = $obj->tva_tx;
$this->recuperableonly = $obj->recuperableonly;
$this->localtax1_tx = $obj->localtax1_tx;
$this->localtax2_tx = $obj->localtax2_tx;
$this->fk_user = $obj->fk_user;
$this->import_key = $obj->import_key;
}
$this->db->free($resql);
return 1;
} else {
$this->error = "Error " . $this->db->lasterror();
dol_syslog(get_class($this) . "::fetch " . $this->error, LOG_ERR);
return - 1;
}
}
/**
* Load all objects in memory from database
*
* @param string $sortorder order
* @param string $sortfield field
* @param int $limit page
* @param int $offset offset
* @param array $filter output
* @return int <0 if KO, >0 if OK
*/
function fetch_all($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = array()) {
global $langs;
$sql = "SELECT";
$sql .= " t.rowid,";
$sql .= " t.entity,";
$sql .= " t.datec,";
$sql .= " t.tms,";
$sql .= " t.fk_product,";
$sql .= " t.fk_soc,";
$sql .= " t.price,";
$sql .= " t.price_ttc,";
$sql .= " t.price_min,";
$sql .= " t.price_min_ttc,";
$sql .= " t.price_base_type,";
$sql .= " t.tva_tx,";
$sql .= " t.recuperableonly,";
$sql .= " t.localtax1_tx,";
$sql .= " t.localtax2_tx,";
$sql .= " t.fk_user,";
$sql .= " t.import_key,";
$sql .= " soc.nom as socname,";
$sql .= " prod.ref as prodref";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_customer_price as t ";
$sql .= " ," . MAIN_DB_PREFIX . "product as prod ";
$sql .= " ," . MAIN_DB_PREFIX . "societe as soc ";
$sql .= " WHERE soc.rowid=t.fk_soc ";
$sql .= " AND prod.rowid=t.fk_product ";
$sql .= " AND prod.entity IN (" . getEntity('product', 1) . ")";
// Manage filter
if (count($filter) > 0) {
foreach ( $filter as $key => $value ) {
if (strpos($key, 'date')) // To allow $filter['YEAR(s.dated)']=>$year
{
$sql .= ' AND ' . $key . ' = \'' . $value . '\'';
} elseif ($key == 'soc.nom') {
$sql .= ' AND ' . $key . ' LIKE \'%' . $value . '%\'';
} else {
$sql .= ' AND ' . $key . ' = ' . $value;
}
}
}
if (! empty($sortfield)) {
$sql .= " ORDER BY " . $sortfield . ' ' . $sortorder;
}
if (! empty($limit)) {
$sql .= ' ' . $this->db->plimit($limit + 1, $offset);
}
dol_syslog(get_class($this) . "::fetch_all sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$this->lines = array ();
$num = $this->db->num_rows($resql);
while ( $obj = $this->db->fetch_object($resql) ) {
$line = new PriceByCustomerLine();
$line->id = $obj->rowid;
$line->entity = $obj->entity;
$line->datec = $this->db->jdate($obj->datec);
$line->tms = $this->db->jdate($obj->tms);
$line->fk_product = $obj->fk_product;
$line->fk_soc = $obj->fk_soc;
$line->price = $obj->price;
$line->price_ttc = $obj->price_ttc;
$line->price_min = $obj->price_min;
$line->price_min_ttc = $obj->price_min_ttc;
$line->price_base_type = $obj->price_base_type;
$line->tva_tx = $obj->tva_tx;
$line->recuperableonly = $obj->recuperableonly;
$line->localtax1_tx = $obj->localtax1_tx;
$line->localtax2_tx = $obj->localtax2_tx;
$line->fk_user = $obj->fk_user;
$line->import_key = $obj->import_key;
$line->socname = $obj->socname;
$line->prodref = $obj->prodref;
$this->lines [] = $line;
}
$this->db->free($resql);
return $num;
} else {
$this->error = "Error " . $this->db->lasterror();
dol_syslog(get_class($this) . "::fetch_all " . $this->error, LOG_ERR);
return - 1;
}
}
/**
* Load all objects in memory from database
*
* @param string $sortorder order
* @param string $sortfield field
* @param int $limit page
* @param int $offset offset
* @param array $filter output
* @return int <0 if KO, >0 if OK
*/
function fetch_all_log($sortorder, $sortfield, $limit, $offset, $filter = array()) {
global $langs;
$sql = "SELECT";
$sql .= " t.rowid,";
$sql .= " t.entity,";
$sql .= " t.datec,";
$sql .= " t.fk_product,";
$sql .= " t.fk_soc,";
$sql .= " t.price,";
$sql .= " t.price_ttc,";
$sql .= " t.price_min,";
$sql .= " t.price_min_ttc,";
$sql .= " t.price_base_type,";
$sql .= " t.tva_tx,";
$sql .= " t.recuperableonly,";
$sql .= " t.localtax1_tx,";
$sql .= " t.localtax2_tx,";
$sql .= " t.fk_user,";
$sql .= " t.import_key,";
$sql .= " soc.nom as socname,";
$sql .= " prod.ref as prodref";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_customer_price_log as t ";
$sql .= " ," . MAIN_DB_PREFIX . "product as prod ";
$sql .= " ," . MAIN_DB_PREFIX . "societe as soc ";
$sql .= " WHERE soc.rowid=t.fk_soc ";
$sql .= " AND prod.rowid=t.fk_product ";
$sql .= " AND prod.entity IN (" . getEntity('product', 1) . ")";
// Manage filter
if (count($filter) > 0) {
foreach ( $filter as $key => $value ) {
if (strpos($key, 'date')) // To allow $filter['YEAR(s.dated)']=>$year
{
$sql .= ' AND ' . $key . ' = \'' . $value . '\'';
} elseif ($key == 'soc.nom') {
$sql .= ' AND ' . $key . ' LIKE \'%' . $value . '%\'';
} else {
$sql .= ' AND ' . $key . ' = ' . $value;
}
}
}
if (! empty($sortfield)) {
$sql .= " ORDER BY " . $sortfield . ' ' . $sortorder;
}
if (! empty($limit)) {
$sql .= ' ' . $this->db->plimit($limit + 1, $offset);
}
dol_syslog(get_class($this) . "::fetch_all_log sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$this->lines = array ();
$num = $this->db->num_rows($resql);
while ( $obj = $this->db->fetch_object($resql) ) {
$line = new PriceByCustomerLine();
$line->id = $obj->rowid;
$line->entity = $obj->entity;
$line->datec = $this->db->jdate($obj->datec);
$line->tms = $this->db->jdate($obj->tms);
$line->fk_product = $obj->fk_product;
$line->fk_soc = $obj->fk_soc;
$line->price = $obj->price;
$line->price_ttc = $obj->price_ttc;
$line->price_min = $obj->price_min;
$line->price_min_ttc = $obj->price_min_ttc;
$line->price_base_type = $obj->price_base_type;
$line->tva_tx = $obj->tva_tx;
$line->recuperableonly = $obj->recuperableonly;
$line->localtax1_tx = $obj->localtax1_tx;
$line->localtax2_tx = $obj->localtax2_tx;
$line->fk_user = $obj->fk_user;
$line->import_key = $obj->import_key;
$line->socname = $obj->socname;
$line->prodref = $obj->prodref;
$this->lines [] = $line;
}
$this->db->free($resql);
return $num;
} else {
$this->error = "Error " . $this->db->lasterror();
dol_syslog(get_class($this) . "::fetch_all_log " . $this->error, LOG_ERR);
return - 1;
}
}
/**
* Update object into database
*
* @param User $user that modifies
* @param int $notrigger triggers after, 1=disable triggers
* @param int $forceupdateaffiliate update price on each soc child
* @return int <0 if KO, >0 if OK
*/
function update($user = 0, $notrigger = 0, $forceupdateaffiliate = 0) {
global $conf, $langs;
$error = 0;
// Clean parameters
if (isset($this->entity))
$this->entity = trim($this->entity);
if (isset($this->fk_product))
$this->fk_product = trim($this->fk_product);
if (isset($this->fk_soc))
$this->fk_soc = trim($this->fk_soc);
if (isset($this->price))
$this->price = trim($this->price);
if (isset($this->price_ttc))
$this->price_ttc = trim($this->price_ttc);
if (isset($this->price_min))
$this->price_min = trim($this->price_min);
if (isset($this->price_min_ttc))
$this->price_min_ttc = trim($this->price_min_ttc);
if (isset($this->price_base_type))
$this->price_base_type = trim($this->price_base_type);
if (isset($this->tva_tx))
$this->tva_tx = trim($this->tva_tx);
if (isset($this->recuperableonly))
$this->recuperableonly = trim($this->recuperableonly);
if (isset($this->localtax1_tx))
$this->localtax1_tx = trim($this->localtax1_tx);
if (isset($this->localtax2_tx))
$this->localtax2_tx = trim($this->localtax2_tx);
if (isset($this->fk_user))
$this->fk_user = trim($this->fk_user);
if (isset($this->import_key))
$this->import_key = trim($this->import_key);
// Check parameters
// Put here code to add a control on parameters values
if ($this->price != '' || $this->price == 0) {
if ($this->price_base_type == 'TTC') {
$this->price_ttc = price2num($this->price, 'MU');
$this->price = price2num($this->price) / (1 + ($this->tva_tx / 100));
$this->price = price2num($this->price, 'MU');
if ($this->price_min != '' || $this->price_min == 0) {
$this->price_min_ttc = price2num($this->price_min, 'MU');
$this->price_min = price2num($this->price_min) / (1 + ($this->tva_tx / 100));
$this->price_min = price2num($this->price_min, 'MU');
} else {
$this->price_min = 0;
$this->price_min_ttc = 0;
}
} else {
$this->price = price2num($this->price, 'MU');
$this->price_ttc = ($this->recuperableonly != 1) ? price2num($this->price) * (1 + ($this->tva_tx / 100)) : $this->price;
$this->price_ttc = price2num($this->price_ttc, 'MU');
if ($this->price_min != '' || $this->price_min == 0) {
$this->price_min = price2num($this->price_min, 'MU');
$this->price_min_ttc = price2num($this->price_min) * (1 + ($this->tva_tx / 100));
$this->price_min_ttc = price2num($this->price_min_ttc, 'MU');
// print 'X'.$newminprice.'-'.$price_min;
} else {
$this->price_min = 0;
$this->price_min_ttc = 0;
}
}
}
// Do a copy of current record into log table
// Insert request
$sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_customer_price_log(";
$sql .= "entity,";
$sql .= "datec,";
$sql .= "fk_product,";
$sql .= "fk_soc,";
$sql .= "price,";
$sql .= "price_ttc,";
$sql .= "price_min,";
$sql .= "price_min_ttc,";
$sql .= "price_base_type,";
$sql .= "tva_tx,";
$sql .= "recuperableonly,";
$sql .= "localtax1_tx,";
$sql .= "localtax2_tx,";
$sql .= "fk_user,";
$sql .= "import_key";
$sql .= ") ";
$sql .= "SELECT";
$sql .= " t.entity,";
$sql .= " t.datec,";
$sql .= " t.fk_product,";
$sql .= " t.fk_soc,";
$sql .= " t.price,";
$sql .= " t.price_ttc,";
$sql .= " t.price_min,";
$sql .= " t.price_min_ttc,";
$sql .= " t.price_base_type,";
$sql .= " t.tva_tx,";
$sql .= " t.recuperableonly,";
$sql .= " t.localtax1_tx,";
$sql .= " t.localtax2_tx,";
$sql .= " t.fk_user,";
$sql .= " t.import_key";
$sql .= " FROM " . MAIN_DB_PREFIX . "product_customer_price as t";
$sql .= " WHERE t.rowid = " . $this->id;
$this->db->begin();
dol_syslog(get_class($this) . "::update sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if (! $resql) {
$error ++;
$this->errors [] = "Error " . $this->db->lasterror();
}
// Update request
$sql = "UPDATE " . MAIN_DB_PREFIX . "product_customer_price SET";
$sql .= " entity=" . $conf->entity . ",";
$sql .= " datec='" . $this->db->idate(dol_now()) . "',";
$sql .= " tms=" . (dol_strlen($this->tms) != 0 ? "'" . $this->db->idate($this->tms) . "'" : 'null') . ",";
$sql .= " fk_product=" . (isset($this->fk_product) ? $this->fk_product : "null") . ",";
$sql .= " fk_soc=" . (isset($this->fk_soc) ? $this->fk_soc : "null") . ",";
$sql .= " price=" . (isset($this->price) ? $this->price : "null") . ",";
$sql .= " price_ttc=" . (isset($this->price_ttc) ? $this->price_ttc : "null") . ",";
$sql .= " price_min=" . (isset($this->price_min) ? $this->price_min : "null") . ",";
$sql .= " price_min_ttc=" . (isset($this->price_min_ttc) ? $this->price_min_ttc : "null") . ",";
$sql .= " price_base_type=" . (isset($this->price_base_type) ? "'" . $this->db->escape($this->price_base_type) . "'" : "null") . ",";
$sql .= " tva_tx=" . (isset($this->tva_tx) ? $this->tva_tx : "null") . ",";
$sql .= " recuperableonly=" . (isset($this->recuperableonly) ? $this->recuperableonly : "null") . ",";
$sql .= " localtax1_tx=" . (isset($this->localtax1_tx) ? $this->localtax1_tx : "null") . ",";
$sql .= " localtax2_tx=" . (isset($this->localtax2_tx) ? $this->localtax2_tx : "null") . ",";
$sql .= " fk_user=" . $user->id . ",";
$sql .= " import_key=" . (isset($this->import_key) ? "'" . $this->db->escape($this->import_key) . "'" : "null") . "";
$sql .= " WHERE rowid=" . $this->id;
dol_syslog(get_class($this) . "::update sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if (! $resql) {
$error ++;
$this->errors [] = "Error " . $this->db->lasterror();
}
if (! $error) {
if (! $notrigger) {
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
// // Call triggers
// include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
// $interface=new Interfaces($this->db);
// $result=$interface->run_triggers('MYOBJECT_MODIFY',$this,$user,$langs,$conf);
// if ($result < 0) { $error++; $this->errors=$interface->errors; }
// // End call triggers
}
}
if (! $error) {
$result = $this->setPriceOnAffiliateThirdparty($user, $forceupdateaffiliate);
if ($result < 0) {
$error ++;
}
}
// Commit or rollback
if ($error) {
foreach ( $this->errors as $errmsg ) {
dol_syslog(get_class($this) . "::update " . $errmsg, LOG_ERR);
$this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
}
$this->db->rollback();
return - 1 * $error;
} else {
$this->db->commit();
return 1;
}
}
/**
* Force update price on child price
*
* @param User $user that modifies
* @param int $forceupdateaffiliate update price on each soc child
* @return int <0 if KO, >0 if OK
*/
function setPriceOnAffiliateThirdparty($user, $forceupdateaffiliate) {
$error = 0;
// Find all susidiaries
$sql = "SELECT s.rowid";
$sql .= " FROM " . MAIN_DB_PREFIX . "societe as s";
$sql .= " WHERE s.parent = " . $this->fk_soc;
$sql .= " AND s.entity IN (" . getEntity('societe', 1) . ")";
dol_syslog(get_class($this) . "::setPriceOnAffiliateThirdparty sql=" . $sql, LOG_DEBUG);
$resql = $this->db->query($sql);
if ($resql) {
$this->lines = array ();
$num = $this->db->num_rows($resql);
while ( ($obj = $this->db->fetch_object($resql)) && (empty($error)) ) {
// find if there is an existing line for the product and the subsidiaries
$prodsocprice = new Productcustomerprice($this->db);
$filter = array (
't.fk_product' => $this->fk_product,'t.fk_soc' => $obj->rowid
);
$result = $prodsocprice->fetch_all('', '', 0, 0, $filter);
if ($result < 0) {
$error ++;
$this->error = $prodsocprice->error;
} else {
// There is one line
if (count($prodsocprice->lines) > 0) {
// If force update => Update
if (! empty($forceupdateaffiliate)) {
$prodsocpriceupd = new Productcustomerprice($this->db);
$prodsocpriceupd->fetch($prodsocprice->lines [0]->id);
$prodsocpriceupd->price = $this->price;
$prodsocpriceupd->price_min = $this->price_min;
$prodsocpriceupd->price_base_type = $this->price_base_type;
$prodsocpriceupd->tva_tx = $this->tva_tx;
$prodsocpriceupd->recuperableonly = $this->recuperableonly;
$resultupd = $prodsocpriceupd->update($user, 0, $forceupdateaffiliate);
if ($result < 0) {
$error ++;
$this->error = $prodsocpriceupd->error;
}
}
} else {
// If line do not exits then create it
$prodsocpricenew = new Productcustomerprice($this->db);
$prodsocpricenew->fk_soc = $obj->rowid;
$prodsocpricenew->fk_product = $this->fk_product;
$prodsocpricenew->price = $this->price;
$prodsocpricenew->price_min = $this->price_min;
$prodsocpricenew->price_base_type = $this->price_base_type;
$prodsocpricenew->tva_tx = $this->tva_tx;
$prodsocpricenew->recuperableonly = $this->recuperableonly;
$resultupd = $prodsocpricenew->create($user, 0, $forceupdateaffiliate);
if ($result < 0) {
$error ++;
$this->error = $prodsocpriceupd->error;
}
}
}
}
$this->db->free($resql);
if (empty($error)) {
return 1;
} else {
return - 1;
}
} else {
$this->error = "Error " . $this->db->lasterror();
dol_syslog(get_class($this) . "::setPriceOnAffiliateThirdparty " . $this->error, LOG_ERR);
return - 1;
}
}
/**
* Delete object in database
*
* @param User $user that deletes
* @param int $notrigger triggers after, 1=disable triggers
* @return int <0 if KO, >0 if OK
*/
function delete($user, $notrigger = 0) {
global $conf, $langs;
$error = 0;
$this->db->begin();
if (! $error) {
if (! $notrigger) {
// Uncomment this and change MYOBJECT to your own tag if you
// want this action calls a trigger.
// // Call triggers
// include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
// $interface=new Interfaces($this->db);
// $result=$interface->run_triggers('MYOBJECT_DELETE',$this,$user,$langs,$conf);
// if ($result < 0) { $error++; $this->errors=$interface->errors; }
// // End call triggers
}
}
if (! $error) {
$sql = "DELETE FROM " . MAIN_DB_PREFIX . "product_customer_price";
$sql .= " WHERE rowid=" . $this->id;
dol_syslog(get_class($this) . "::delete sql=" . $sql);
$resql = $this->db->query($sql);
if (! $resql) {
$error ++;
$this->errors [] = "Error " . $this->db->lasterror();
}
}
// Commit or rollback
if ($error) {
foreach ( $this->errors as $errmsg ) {
dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR);
$this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
}
$this->db->rollback();
return - 1 * $error;
} else {
$this->db->commit();
return 1;
}
}
/**
* Load an object from its id and create a new one in database
*
* @param int $fromid of object to clone
* @return int id of clone
*/
function createFromClone($fromid) {
global $user, $langs;
$error = 0;
$object = new Productcustomerprice($this->db);
$this->db->begin();
// Load source object
$object->fetch($fromid);
$object->id = 0;
$object->statut = 0;
// Clear fields
// ...
// Create clone
$result = $object->create($user);
// Other options
if ($result < 0) {
$this->error = $object->error;
$error ++;
}
if (! $error) {
}
// End
if (! $error) {
$this->db->commit();
return $object->id;
} else {
$this->db->rollback();
return - 1;
}
}
/**
* Initialise object with example values
* Id must be 0 if object instance is a specimen
*
* @return void
*/
function initAsSpecimen() {
$this->id = 0;
$this->entity = '';
$this->datec = '';
$this->tms = '';
$this->fk_product = '';
$this->fk_soc = '';
$this->price = '';
$this->price_ttc = '';
$this->price_min = '';
$this->price_min_ttc = '';
$this->price_base_type = '';
$this->tva_tx = '';
$this->recuperableonly = '';
$this->localtax1_tx = '';
$this->localtax2_tx = '';
$this->fk_user = '';
$this->import_key = '';
}
}
/**
* File of class to manage predefined price products or services by customer lines
*/
class PriceByCustomerLine
{
var $id;
var $entity;
var $datec = '';
var $tms = '';
var $fk_product;
var $fk_soc;
var $price;
var $price_ttc;
var $price_min;
var $price_min_ttc;
var $price_base_type;
var $tva_tx;
var $recuperableonly;
var $localtax1_tx;
var $localtax2_tx;
var $fk_user;
var $import_key;
var $socname;
var $prodref;
}
?>

File diff suppressed because it is too large Load Diff

565
htdocs/societe/price.php Normal file
View File

@ -0,0 +1,565 @@
<?php
/* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
* Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
* Copyright (C) 2005-2013 Regis Houssin <regis.houssin@capnetworks.com>
* Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/societe/price.php
* \ingroup product
* \brief Page to show product prices by customer
*/
require '../main.inc.php';
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/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
$prodcustprice = new Productcustomerprice($db);
}
$langs->load("products");
$langs->load("companies");
$langs->load("bills");
$action = GETPOST('action', 'alpha');
// Security check
$socid = GETPOST('socid', 'int');
if ($user->societe_id)
$socid = $user->societe_id;
$result = restrictedArea($user, 'societe', $socid, '&societe');
/**
* ***************************************************
* Price by customer
* ****************************************************
*/
if ($action == 'add_customer_price_confirm' && ! $_POST ["cancel"] && ($user->rights->produit->creer || $user->rights->service->creer)) {
$update_child_soc = GETPOST('updatechildprice');
// add price by customer
$prodcustprice->fk_soc = $socid;
$prodcustprice->fk_product = GETPOST('prodid', 'int');
$prodcustprice->price = price2num(GETPOST("price"), 'MU');
$prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU');
$prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha');
$prodcustprice->tva_tx = str_replace('*', '', GETPOST("tva_tx"));
$prodcustprice->recuperableonly = (preg_match('/\*/', GETPOST("tva_tx")) ? 1 : 0);
$result = $prodcustprice->create($user, 0, $update_child_soc);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
} else {
setEventMessage($langs->trans('Save'), 'mesgs');
}
$action = '';
}
if ($action == 'delete_customer_price' && ($user->rights->produit->creer || $user->rights->service->creer)) {
// Delete price by customer
$prodcustprice->id = GETPOST('lineid');
$result = $prodcustprice->delete($user);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'mesgs');
} else {
setEventMessage($langs->trans('Delete'), 'errors');
}
$action = '';
}
if ($action == 'update_customer_price_confirm' && ! $_POST ["cancel"] && ($user->rights->produit->creer || $user->rights->service->creer)) {
$prodcustprice->fetch(GETPOST('lineid', 'int'));
$update_child_soc = GETPOST('updatechildprice');
// update price by customer
$prodcustprice->price = price2num(GETPOST("price"), 'MU');
$prodcustprice->price_min = price2num(GETPOST("price_min"), 'MU');
$prodcustprice->price_base_type = GETPOST("price_base_type", 'alpha');
$prodcustprice->tva_tx = str_replace('*', '', GETPOST("tva_tx"));
$prodcustprice->recuperableonly = (preg_match('/\*/', GETPOST("tva_tx")) ? 1 : 0);
$result = $prodcustprice->update($user, 0, $update_child_soc);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
} else {
setEventMessage($langs->trans('Save'), 'mesgs');
}
$action = '';
}
/*
* View
*/
$form = new Form($db);
$soc = new Societe($db);
$result = $soc->fetch($socid);
llxHeader("", $langs->trans("ThirdParty") . '-' . $langs->trans('PriceByCustomer'));
if (! empty($conf->notification->enabled))
$langs->load("mails");
$head = societe_prepare_head($soc);
dol_fiche_head($head, 'price', $langs->trans("ThirdParty"), 0, 'company');
print '<table class="border" width="100%">';
print '<tr><td width="25%">' . $langs->trans("ThirdPartyName") . '</td><td colspan="3">';
print $form->showrefnav($soc, 'socid', '', ($user->societe_id ? 0 : 1), 'rowid', 'nom');
print '</td></tr>';
if (! empty($conf->global->SOCIETE_USEPREFIX)) // Old not used prefix field
{
print '<tr><td>' . $langs->trans('Prefix') . '</td><td colspan="3">' . $soc->prefix_comm . '</td></tr>';
}
if ($soc->client) {
print '<tr><td>';
print $langs->trans('CustomerCode') . '</td><td colspan="3">';
print $soc->code_client;
if ($soc->check_codeclient() != 0)
print ' <font class="error">(' . $langs->trans("WrongCustomerCode") . ')</font>';
print '</td></tr>';
}
if ($soc->fournisseur) {
print '<tr><td>';
print $langs->trans('SupplierCode') . '</td><td colspan="3">';
print $soc->code_fournisseur;
if ($soc->check_codefournisseur() != 0)
print ' <font class="error">(' . $langs->trans("WrongSupplierCode") . ')</font>';
print '</td></tr>';
}
if (! empty($conf->barcode->enabled)) {
print '<tr><td>' . $langs->trans('Gencod') . '</td><td colspan="3">' . $soc->barcode . '</td></tr>';
}
print "<tr><td valign=\"top\">" . $langs->trans('Address') . "</td><td colspan=\"3\">";
dol_print_address($soc->address, 'gmap', 'thirdparty', $soc->id);
print "</td></tr>";
// Zip / Town
print '<tr><td width="25%">' . $langs->trans('Zip') . '</td><td width="25%">' . $soc->zip . "</td>";
print '<td width="25%">' . $langs->trans('Town') . '</td><td width="25%">' . $soc->town . "</td></tr>";
// Country
if ($soc->country) {
print '<tr><td>' . $langs->trans('Country') . '</td><td colspan="3">';
$img = picto_from_langcode($soc->country_code);
print($img ? $img . ' ' : '');
print $soc->country;
print '</td></tr>';
}
// EMail
print '<tr><td>' . $langs->trans('EMail') . '</td><td colspan="3">';
print dol_print_email($soc->email, 0, $soc->id, 'AC_EMAIL');
print '</td></tr>';
// Web
print '<tr><td>' . $langs->trans('Web') . '</td><td colspan="3">';
print dol_print_url($soc->url);
print '</td></tr>';
// Phone / Fax
print '<tr><td>' . $langs->trans('Phone') . '</td><td>' . dol_print_phone($soc->tel, $soc->country_code, 0, $soc->id, 'AC_TEL') . '</td>';
print '<td>' . $langs->trans('Fax') . '</td><td>' . dol_print_phone($soc->fax, $soc->country_code, 0, $soc->id, 'AC_FAX') . '</td></tr>';
print '</table>';
print '</div>';
if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) {
$prodcustprice = new Productcustomerprice($db);
$sortfield = GETPOST("sortfield", 'alpha');
$sortorder = GETPOST("sortorder", 'alpha');
$page = GETPOST("page", 'int');
if ($page == - 1) {
$page = 0;
}
$offset = $conf->liste_limit * $page;
$pageprev = $page - 1;
$pagenext = $page + 1;
if (! $sortorder)
$sortorder = "ASC";
if (! $sortfield)
$sortfield = "soc.nom";
// Build filter to diplay only concerned lines
$filter = array (
't.fk_soc' => $soc->id
);
$search_soc = GETPOST('search_soc');
if (! empty($search_soc)) {
$filter ['soc.nom'] = $search_soc;
}
if ($action == 'add_customer_price') {
// Create mode
print_fiche_titre($langs->trans('PriceByCustomer'));
print '<form action="' . $_SERVER ["PHP_SELF"] . '?socid=' . $soc->id . '" method="POST">';
print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
print '<input type="hidden" name="action" value="add_customer_price_confirm">';
print '<input type="hidden" name="socid" value="' . $soc->id . '">';
print '<table class="border" width="100%">';
print '<tr>';
print '<td>' . $langs->trans('Product') . '</td>';
print '<td>';
print $form->select_produits('', 'prodid', '', 0);
print '</td>';
print '</tr>';
// VAT
print '<tr><td>' . $langs->trans("VATRate") . '</td><td>';
print $form->load_tva("tva_tx", $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr);
print '</td></tr>';
// Price base
print '<tr><td width="15%">';
print $langs->trans('PriceBase');
print '</td>';
print '<td>';
print $form->select_PriceBaseType($object->price_base_type, "price_base_type");
print '</td>';
print '</tr>';
// Price
print '<tr><td width="20%">';
$text = $langs->trans('SellingPrice');
print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1);
print '</td><td>';
if ($object->price_base_type == 'TTC') {
print '<input name="price" size="10" value="' . price($object->price_ttc) . '">';
} else {
print '<input name="price" size="10" value="' . price($object->price) . '">';
}
print '</td></tr>';
// Price minimum
print '<tr><td>';
$text = $langs->trans('MinPrice');
print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1);
if ($object->price_base_type == 'TTC') {
print '<td><input name="price_min" size="10" value="' . price($object->price_min_ttc) . '">';
} else {
print '<td><input name="price_min" size="10" value="' . price($object->price_min) . '">';
}
print '</td></tr>';
// Update all child soc
print '<tr><td width="15%">';
print $langs->trans('ForceUpdateChildPriceSoc');
print '</td>';
print '<td>';
print '<input type="checkbox" name="updatechildprice" value="1"/>';
print '</td>';
print '</tr>';
print '</table>';
print '<center><br><input type="submit" class="button" value="' . $langs->trans("Save") . '">&nbsp;';
print '<input type="submit" class="button" name="cancel" value="' . $langs->trans("Cancel") . '"></center>';
print '<br></form>';
} elseif ($action == 'edit_customer_price') {
// Edit mode
print_fiche_titre($langs->trans('PriceByCustomer'));
$result = $prodcustprice->fetch(GETPOST('lineid', 'int'));
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
}
print '<form action="' . $_SERVER ["PHP_SELF"] . '?socid=' . $soc->id . '" method="POST">';
print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
print '<input type="hidden" name="action" value="update_customer_price_confirm">';
print '<input type="hidden" name="lineid" value="' . $prodcustprice->id . '">';
print '<table class="border" width="100%">';
print '<tr>';
print '<td>' . $langs->trans('Product') . '</td>';
$staticprod = new Product($db);
$staticprod->fetch($prodcustprice->fk_product);
print "<td>" . $staticprod->getNomUrl(1) . "</td>";
print '</tr>';
// VAT
print '<tr><td>' . $langs->trans("VATRate") . '</td><td>';
print $form->load_tva("tva_tx", $prodcustprice->tva_tx, $mysoc, '', $staticprod->id, $prodcustprice->recuperableonly);
print '</td></tr>';
// Price base
print '<tr><td width="15%">';
print $langs->trans('PriceBase');
print '</td>';
print '<td>';
print $form->select_PriceBaseType($prodcustprice->price_base_type, "price_base_type");
print '</td>';
print '</tr>';
// Price
print '<tr><td width="20%">';
$text = $langs->trans('SellingPrice');
print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1);
print '</td><td>';
if ($prodcustprice->price_base_type == 'TTC') {
print '<input name="price" size="10" value="' . price($prodcustprice->price_ttc) . '">';
} else {
print '<input name="price" size="10" value="' . price($prodcustprice->price) . '">';
}
print '</td></tr>';
// Price minimum
print '<tr><td>';
$text = $langs->trans('MinPrice');
print $form->textwithpicto($text, $langs->trans("PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT), 1, 1);
if ($prodcustprice->price_base_type == 'TTC') {
print '<td><input name="price_min" size="10" value="' . price($prodcustprice->price_min_ttc) . '">';
} else {
print '<td><input name="price_min" size="10" value="' . price($prodcustprice->price_min) . '">';
}
print '</td></tr>';
// Update all child soc
print '<tr><td width="15%">';
print $langs->trans('ForceUpdateChildPriceSoc');
print '</td>';
print '<td>';
print '<input type="checkbox" name="updatechildprice" value="1">';
print '</td>';
print '</tr>';
print '</table>';
print '<center><br><input type="submit" class="button" value="' . $langs->trans("Save") . '">&nbsp;';
print '<input type="submit" class="button" name="cancel" value="' . $langs->trans("Cancel") . '"></center>';
print '<br></form>';
} elseif ($action == 'showlog_customer_price') {
$filter = array (
't.fk_product' => GETPOST('prodid', 'int'),'t.fk_soc' => $socid
);
// Count total nb of records
$nbtotalofrecords = 0;
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
$nbtotalofrecords = $prodcustprice->fetch_all_log($sortorder, $sortfield, $conf->liste_limit, $offset, $filter);
}
$result = $prodcustprice->fetch_all_log($sortorder, $sortfield, $conf->liste_limit, $offset, $filter);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
}
$option = '&socid=' . GETPOST('socid', 'int') . '&prodid=' . GETPOST('prodid', 'int');
print_barre_liste($langs->trans('PriceByCustomerLog'), $page, $_SERVEUR ['PHP_SELF'], $option, $sortfield, $sortorder, '', count($prodcustprice->lines), $nbtotalofrecords);
if (count($prodcustprice->lines) > 0) {
print '<form action="' . $_SERVER ["PHP_SELF"] . '?id=' . $object->id . '" method="POST">';
print '<input type="hidden" name="id" value="' . $object->id . '">';
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>' . $langs->trans("Product") . '</td>';
print '<td>' . $langs->trans("AppliedPricesFrom") . '</td>';
print '<td align="center">' . $langs->trans("PriceBase") . '</td>';
print '<td align="right">' . $langs->trans("VAT") . '</td>';
print '<td align="right">' . $langs->trans("HT") . '</td>';
print '<td align="right">' . $langs->trans("TTC") . '</td>';
print '<td align="right">' . $langs->trans("MinPrice") . ' ' . $langs->trans("HT") . '</td>';
print '<td align="right">' . $langs->trans("MinPrice") . ' ' . $langs->trans("TTC") . '</td>';
print '<td align="right">' . $langs->trans("ChangedBy") . '</td>';
print '<td>&nbsp;</td>';
print '</tr>';
$var = True;
foreach ( $prodcustprice->lines as $line ) {
print "<tr $bc[$var]>";
$staticprod = new Product($db);
$staticprod->fetch($line->fk_product);
print "<td>" . $staticprod->getNomUrl(1) . "</td>";
print "<td>" . dol_print_date($line->datec, "dayhour") . "</td>";
print '<td align="center">' . $langs->trans($line->price_base_type) . "</td>";
print '<td align="right">' . vatrate($line->tva_tx, true, $line->recuperableonly) . "</td>";
print '<td align="right">' . price($line->price) . "</td>";
print '<td align="right">' . price($line->price_ttc) . "</td>";
print '<td align="right">' . price($line->price_min) . '</td>';
print '<td align="right">' . price($line->price_min_ttc) . '</td>';
// User
$userstatic = new User($db);
$userstatic->fetch($line->fk_user);
print '<td align="right">';
print $userstatic->getLoginUrl(1);
print '</td>';
}
print "</table>";
} else {
print $langs->trans('None');
}
print "\n" . '<div class="tabsAction">' . "\n";
print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER ["PHP_SELF"] . '?socid=' . $soc->id . '">' . $langs->trans("Ok") . '</a></div>';
print "\n</div><br>\n";
} else {
// View mode
// Count total nb of records
$nbtotalofrecords = 0;
if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
$nbtotalofrecords = $prodcustprice->fetch_all('', '', 0, 0, $filter);
}
$result = $prodcustprice->fetch_all($sortorder, $sortfield, $conf->liste_limit, $offset, $filter);
if ($result < 0) {
setEventMessage($prodcustprice->error, 'errors');
}
$option = '&search_soc=' . $search_soc . '&id=' . $object->id;
print_barre_liste($langs->trans('PriceByCustomer'), $page, $_SERVEUR ['PHP_SELF'], $option, $sortfield, $sortorder, '', count($prodcustprice->lines), $nbtotalofrecords);
if (count($prodcustprice->lines) > 0) {
print '<form action="' . $_SERVER ["PHP_SELF"] . '?id=' . $object->id . '" method="POST">';
print '<input type="hidden" name="id" value="' . $object->id . '">';
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>' . $langs->trans("Product") . '</td>';
print '<td>' . $langs->trans("AppliedPricesFrom") . '</td>';
print '<td align="center">' . $langs->trans("PriceBase") . '</td>';
print '<td align="right">' . $langs->trans("VAT") . '</td>';
print '<td align="right">' . $langs->trans("HT") . '</td>';
print '<td align="right">' . $langs->trans("TTC") . '</td>';
print '<td align="right">' . $langs->trans("MinPrice") . ' ' . $langs->trans("HT") . '</td>';
print '<td align="right">' . $langs->trans("MinPrice") . ' ' . $langs->trans("TTC") . '</td>';
print '<td align="right">' . $langs->trans("ChangedBy") . '</td>';
print '<td>&nbsp;</td>';
print '</tr>';
print '<tr class="liste_titre">';
print '<td><input type="text" class="flat" name="search_soc" value="' . $search_soc . '" size="20"></td>';
print '<td colspan="8">&nbsp;</td>';
// Print the search button
print '<td class="liste_titre" align="right">';
print '<input class="liste_titre" name="button_search" type="image" src="' . DOL_URL_ROOT . '/theme/' . $conf->theme . '/img/search.png" value="' . dol_escape_htmltag($langs->trans("Search")) . '" title="' . dol_escape_htmltag($langs->trans("Search")) . '">';
print '</td>';
print '</tr>';
$var = True;
foreach ( $prodcustprice->lines as $line ) {
print "<tr $bc[$var]>";
$staticprod = new Product($db);
$staticprod->fetch($line->fk_product);
print "<td>" . $staticprod->getNomUrl(1) . "</td>";
print "<td>" . dol_print_date($line->datec, "dayhour") . "</td>";
print '<td align="center">' . $langs->trans($line->price_base_type) . "</td>";
print '<td align="right">' . vatrate($line->tva_tx, true, $line->recuperableonly) . "</td>";
print '<td align="right">' . price($line->price) . "</td>";
print '<td align="right">' . price($line->price_ttc) . "</td>";
print '<td align="right">' . price($line->price_min) . '</td>';
print '<td align="right">' . price($line->price_min_ttc) . '</td>';
// User
$userstatic = new User($db);
$userstatic->fetch($line->fk_user);
print '<td align="right">';
print $userstatic->getLoginUrl(1);
print '</td>';
// Todo Edit or delete button
// Action
if ($user->rights->produit->creer || $user->rights->service->creer) {
print '<td align="right">';
print '<a href="' . $_SERVER ["PHP_SELF"] . '?action=delete_customer_price&amp;socid=' . $soc->id . '&amp;lineid=' . $line->id . '">';
print img_delete();
print '</a>';
print '<a href="' . $_SERVER ["PHP_SELF"] . '?action=edit_customer_price&amp;socid=' . $soc->id . '&amp;lineid=' . $line->id . '">';
print img_edit();
print '</a>';
print '<a href="' . $_SERVER ["PHP_SELF"] . '?action=showlog_customer_price&amp;socid=' . $soc->id . '&amp;prodid=' . $line->fk_product . '">';
print img_info();
print '</a>';
print '</td>';
}
print "</tr>\n";
}
print "</table>";
print "</form>";
} else {
print $langs->trans('None');
}
/* ************************************************************************** */
/* */
/* Barre d'action */
/* */
/* ************************************************************************** */
print "\n" . '<div class="tabsAction">' . "\n";
if ($user->rights->produit->creer || $user->rights->service->creer) {
print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER ["PHP_SELF"] . '?action=add_customer_price&amp;socid=' . $soc->id . '">' . $langs->trans("AddCustomerPrice") . '</a></div>';
}
print "\n</div><br>\n";
}
}
llxFooter();
$db->close();
?>