diff --git a/ChangeLog b/ChangeLog index da09d71d189..f0f038b7235 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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. diff --git a/htdocs/comm/propal.php b/htdocs/comm/propal.php index 4ad74c01af3..7a4ec48f04b 100644 --- a/htdocs/comm/propal.php +++ b/htdocs/comm/propal.php @@ -8,7 +8,7 @@ * Copyright (C) 2010-2013 Juanjo Menent * Copyright (C) 2010-2011 Philippe Grand * Copyright (C) 2012-2013 Christophe Battarel - * Copyright (C) 2013 Florian Henry + * Copyright (C) 2013-2014 Florian Henry * * 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 @@ -726,6 +726,29 @@ else if (($action == 'addline' || $action == 'addline_predef') && $user->rights- $price_min = $prod->multiprices_min[$object->client->price_level]; $price_base_type = $prod->multiprices_base_type[$object->client->price_level]; } + elseif (! empty ( $conf->global->PRODUIT_CUSTOMER_PRICES )) { + require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php'; + + $prodcustprice = new Productcustomerprice ( $db ); + + $filter = array ( + 't.fk_product' => $prod->id, + 't.fk_soc'=> $object->client->id + ); + + $result = $prodcustprice->fetch_all ( '', '', 0,0, $filter ); + if ($result) + { + if (count($prodcustprice->lines)>0) + { + $found=true; + $pu_ht=price($prodcustprice->lines[0]->price); + $pu_ttc=price($prodcustprice->lines[0]->price_ttc); + $price_base_type=$prodcustprice->lines[0]->price_base_type; + $prod->tva_tx=$prodcustprice->lines[0]->tva_tx; + } + } + } else { $pu_ht = $prod->price; diff --git a/htdocs/commande/fiche.php b/htdocs/commande/fiche.php index 480fdb95841..05bc800468e 100644 --- a/htdocs/commande/fiche.php +++ b/htdocs/commande/fiche.php @@ -668,6 +668,29 @@ else if ($action == 'addline' && $user->rights->commande->creer) $price_min = $prod->multiprices_min[$object->client->price_level]; $price_base_type = $prod->multiprices_base_type[$object->client->price_level]; } + elseif (! empty ( $conf->global->PRODUIT_CUSTOMER_PRICES )) { + require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php'; + + $prodcustprice = new Productcustomerprice ( $db ); + + $filter = array ( + 't.fk_product' => $prod->id, + 't.fk_soc'=> $object->client->id + ); + + $result = $prodcustprice->fetch_all ( '', '', 0,0, $filter ); + if ($result) + { + if (count($prodcustprice->lines)>0) + { + $found=true; + $pu_ht=price($prodcustprice->lines[0]->price); + $pu_ttc=price($prodcustprice->lines[0]->price_ttc); + $price_base_type=$prodcustprice->lines[0]->price_base_type; + $prod->tva_tx=$prodcustprice->lines[0]->tva_tx; + } + } + } else { $pu_ht = $prod->price; diff --git a/htdocs/compta/facture.php b/htdocs/compta/facture.php index de05b11a64c..cf42be68c0c 100644 --- a/htdocs/compta/facture.php +++ b/htdocs/compta/facture.php @@ -8,7 +8,7 @@ * Copyright (C) 2010-2013 Juanjo Menent * Copyright (C) 2012-2013 Christophe Battarel * Copyright (C) 2013 Jean-Francois FERRY - * Copyright (C) 2013 Florian Henry + * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2013 Cédric Salvador * * This program is free software; you can redistribute it and/or modify @@ -1235,6 +1235,29 @@ else if (($action == 'addline' || $action == 'addline_predef') && $user->rights- $price_min = $prod->multiprices_min[$object->client->price_level]; $price_base_type = $prod->multiprices_base_type[$object->client->price_level]; } + elseif (! empty ( $conf->global->PRODUIT_CUSTOMER_PRICES )) { + require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php'; + + $prodcustprice = new Productcustomerprice ( $db ); + + $filter = array ( + 't.fk_product' => $prod->id, + 't.fk_soc'=> $object->client->id + ); + + $result = $prodcustprice->fetch_all ( '', '', 0,0, $filter ); + if ($result) + { + if (count($prodcustprice->lines)>0) + { + $found=true; + $pu_ht=price($prodcustprice->lines[0]->price); + $pu_ttc=price($prodcustprice->lines[0]->price_ttc); + $price_base_type=$prodcustprice->lines[0]->price_base_type; + $prod->tva_tx=$prodcustprice->lines[0]->tva_tx; + } + } + } else { $pu_ht = $prod->price; diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index fa61089a853..2dc8a454ae0 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -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 diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index 42da0b04d38..aa0a422d91f 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -3,7 +3,7 @@ * Copyright (C) 2006 Rodolphe Quiedeville * Copyright (C) 2007 Patrick Raguin * Copyright (C) 2010-2012 Regis Houssin - * Copyright (C) 2013 Florian Henry + * Copyright (C) 2013-2014 Florian Henry * Copyright (C) 2013 Juanjo Menent * Copyright (C) 2013 Christophe Battarel * Copyright (C) 2013 Alexandre Spangaro @@ -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"); diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 19d2adeea93..3e73d4320c3 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -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 diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index 8d9c3bdd18b..205791624c1 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -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) { diff --git a/htdocs/core/tpl/objectline_add.tpl.php b/htdocs/core/tpl/objectline_add.tpl.php index 0c03206ae67..d27268be121 100644 --- a/htdocs/core/tpl/objectline_add.tpl.php +++ b/htdocs/core/tpl/objectline_add.tpl.php @@ -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); } ?> | @@ -270,6 +270,9 @@ $(document).ready(function() { 'id': $(this).val(), 'price_level': price_level)?1:$buyer->price_level; ?>, 'pbq': $("option:selected", this).attr('pbq') + global->PRODUIT_CUSTOMER_PRICES )) {?> + ,'socid': id; ?> + }, function(data) { if (typeof data != 'undefined') { diff --git a/htdocs/core/tpl/predefinedproductline_create.tpl.php b/htdocs/core/tpl/predefinedproductline_create.tpl.php index acd06c807d3..ff39c9b705c 100644 --- a/htdocs/core/tpl/predefinedproductline_create.tpl.php +++ b/htdocs/core/tpl/predefinedproductline_create.tpl.php @@ -101,7 +101,7 @@ else { echo ''; $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 ''; if (is_object($hookmanager)) diff --git a/htdocs/install/mysql/migration/3.5.0-3.6.0.sql b/htdocs/install/mysql/migration/3.5.0-3.6.0.sql index 1a2a9bc9c75..0a845dc76f8 100755 --- a/htdocs/install/mysql/migration/3.5.0-3.6.0.sql +++ b/htdocs/install/mysql/migration/3.5.0-3.6.0.sql @@ -958,4 +958,55 @@ 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', '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 ref; +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; diff --git a/htdocs/install/mysql/tables/llx_product_customer_price.key.sql b/htdocs/install/mysql/tables/llx_product_customer_price.key.sql new file mode 100644 index 00000000000..8ae2e2ca9a8 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_product_customer_price.key.sql @@ -0,0 +1,30 @@ +-- ============================================================================ +-- Copyright (C) 2003 Rodolphe Quiedeville +-- Copyright (C) 2005-2012 Laurent Destailleur +-- Copyright (C) 2009-2012 Regis Houssin +-- Copyright (C) 2013 Florian Henry +-- +-- 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 . +-- +-- ============================================================================ + + +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; diff --git a/htdocs/install/mysql/tables/llx_product_customer_price.sql b/htdocs/install/mysql/tables/llx_product_customer_price.sql new file mode 100644 index 00000000000..0dd37358682 --- /dev/null +++ b/htdocs/install/mysql/tables/llx_product_customer_price.sql @@ -0,0 +1,42 @@ +-- ============================================================================ +-- Copyright (C) 2003 Rodolphe Quiedeville +-- Copyright (C) 2009-2011 Laurent Destailleur +-- Copyright (C) 2009-2013 Regis Houssin +-- Copyright (C) 2012 Juanjo Menent +-- Copyright (C) 2013 Florian Henry +-- +-- 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 . +-- +-- ============================================================================ + +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; diff --git a/htdocs/install/mysql/tables/llx_product_customer_price_log.sql b/htdocs/install/mysql/tables/llx_product_customer_price_log.sql new file mode 100644 index 00000000000..b25bd982aab --- /dev/null +++ b/htdocs/install/mysql/tables/llx_product_customer_price_log.sql @@ -0,0 +1,39 @@ +-- ============================================================================ +-- Copyright (C) 2005 Rodolphe Quiedeville +-- Copyright (C) 2009 Laurent Destailleur +-- Copyright (C) 2013 Florian Henry +-- +-- 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 . +-- +-- ============================================================================ + +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; diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 95dfb0e35b0..a84d929550a 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -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 \ No newline at end of file diff --git a/htdocs/langs/fr_FR/products.lang b/htdocs/langs/fr_FR/products.lang index d8c8c3e76d8..474e1e95873 100644 --- a/htdocs/langs/fr_FR/products.lang +++ b/htdocs/langs/fr_FR/products.lang @@ -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 \ No newline at end of file diff --git a/htdocs/product/admin/product.php b/htdocs/product/admin/product.php index aaea6a2fd18..4d5cc811e85 100644 --- a/htdocs/product/admin/product.php +++ b/htdocs/product/admin/product.php @@ -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 ' '."\n"; * Formulaire parametres divers */ -// multiprix activation/desactivation + $var=!$var; print '
'; print ''; -print ''; +print ''; print ''; -print ''.$langs->trans("MultiPricesAbility").''; +print ''.$langs->trans("PricingRule").''; print ''; -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 ''; print ''; print ''; diff --git a/htdocs/product/ajax/products.php b/htdocs/product/ajax/products.php index 35b9c2a6473..990b154d0eb 100644 --- a/htdocs/product/ajax/products.php +++ b/htdocs/product/ajax/products.php @@ -72,7 +72,7 @@ if (! empty($action) && $action == 'fetch' && ! empty($id)) $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 "; @@ -96,7 +96,7 @@ if (! empty($action) && $action == 'fetch' && ! empty($id)) } // 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 "; @@ -120,7 +120,34 @@ if (! empty($action) && $action == 'fetch' && ! empty($id)) } } } - + + //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; + } + } + } + + if (! $found) { $outprice_ht=price($object->price); @@ -158,11 +185,11 @@ else $form = new Form($db); if (empty($mode) || $mode == 1) { - $arrayresult=$form->select_produits_list("",$htmlname,$type,"",$price_level,$searchkey,$status,2,$outjson); + $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); + $arrayresult=$form->select_produits_fournisseurs_list($socid,"",$htmlname,$type,"",$searchkey,$status,$outjson,$socid); } $db->close(); diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 42209bbcca1..1c94cf5f3c6 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -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); diff --git a/htdocs/product/class/productcustomerprice.class.php b/htdocs/product/class/productcustomerprice.class.php new file mode 100644 index 00000000000..cd32271b795 --- /dev/null +++ b/htdocs/product/class/productcustomerprice.class.php @@ -0,0 +1,954 @@ + + * Copyright (C) 2012-2013 Florian Henry + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/product/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'; + +/** + * Put here description of your class + */ +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 + * @param int $arch archive or not + * @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 + * @param int $arch archive or not + * @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 = ''; + } +} + +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; +} +?> diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 0a245093057..f510a0bf517 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -1,9 +1,10 @@ - * Copyright (C) 2004-2013 Laurent Destailleur + * Copyright (C) 2004-2012 Laurent Destailleur * Copyright (C) 2005 Eric Seigne * Copyright (C) 2005-2013 Regis Houssin * Copyright (C) 2006 Andre Cianfarani + * Copyright (C) 2014 Florian Henry * * 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 @@ -29,6 +30,12 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.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("bills"); @@ -51,7 +58,7 @@ $object = new Product($db); if ($action == 'update_price' && ! $_POST["cancel"] && ($user->rights->produit->creer || $user->rights->service->creer)) { $result = $object->fetch($id); - + // MultiPrix if (! empty($conf->global->PRODUIT_MULTIPRICES)) { @@ -112,7 +119,7 @@ $error=0; if ($action == 'activate_price_by_qty') { // Activating product price by quantity add a new price, specified as by quantity $result = $object->fetch($id); $level=GETPOST('level'); - + $object->updatePrice(0, $object->price_base_type, $user, $object->tva_tx, 0, $level, $object->tva_npr, 1); } @@ -131,7 +138,7 @@ if ($action == 'update_price_by_qty') { // Ajout / Mise à jour d'un prix par qu $quantity=GETPOST('quantity'); $remise_percent=price2num(GETPOST('remise_percent')); $remise=0; // TODO : allow dicsount by amount when available on documents - + if (empty($quantity)) { $error++; @@ -148,10 +155,10 @@ if ($action == 'update_price_by_qty') { // Ajout / Mise à jour d'un prix par qu { $price = price2num($newprice) / (1 + ($object->tva_tx / 100)); } - + $price = price2num($newprice,'MU'); $unitPrice = price2num($price/$quantity,'MU'); - + // Ajout / mise à jour if($rowid > 0) { $sql = "UPDATE ".MAIN_DB_PREFIX."product_price_by_qty SET"; @@ -161,12 +168,12 @@ if ($action == 'update_price_by_qty') { // Ajout / Mise à jour d'un prix par qu $sql.= " remise_percent=".$remise_percent.","; $sql.= " remise=".$remise; $sql.= " WHERE rowid = ".GETPOST('rowid'); - + $result = $db->query($sql); } 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); } } @@ -174,22 +181,94 @@ if ($action == 'update_price_by_qty') { // Ajout / Mise à jour d'un prix par qu if ($action == 'delete_price_by_qty') { $rowid = GETPOST('rowid'); - + $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price_by_qty"; $sql.= " WHERE rowid = ".GETPOST('rowid'); - + $result = $db->query($sql); } if ($action == 'delete_all_price_by_qty') { $priceid=GETPOST('priceid'); - + $sql = "DELETE FROM ".MAIN_DB_PREFIX."product_price_by_qty"; $sql.= " WHERE fk_product_price = ".$priceid; - + $result = $db->query($sql); } +/***************************************************** + * Price by customer +*****************************************************/ +if ($action == 'add_customer_price_confirm' && ! $_POST["cancel"] && ($user->rights->produit->creer || $user->rights->service->creer)) +{ + + $update_child_soc=GETPOST('updatechildprice'); + + $result = $object->fetch($id); + + //add price by customer + $prodcustprice->fk_soc=GETPOST('socid','int'); + $prodcustprice->fk_product=$object->id; + $prodcustprice->price=price2num(GETPOST("price"),'MU'); + $prodcustprice->price_min=price2num(GETPOST("price_min"),'MU'); + $prodcustprice->price_base_type=GETPOST("price_base_type",'alpha'); + $prodcustprice->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->supprimer || $user->rights->service->supprimer)) +{ + //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)) +{ + + $update_child_soc=GETPOST('updatechildprice'); + + $prodcustprice->fetch(GETPOST('lineid','int')); + + //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=''; +} + /* @@ -207,7 +286,6 @@ $titre=$langs->trans("CardProduct".$object->type); $picto=($object->type==1?'service':'product'); dol_fiche_head($head, 'price', $titre, 0, $picto); - print ''; // Ref @@ -325,10 +403,10 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) if($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) { print ''; - + // Price by quantity - if($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) + if($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) { print '
'.$langs->trans("PriceByQuantity").' '.$i; print ''; - + if($object->prices_by_qty[$i] == 1) { print ''; - + print ''; print ''; print ''; @@ -383,7 +461,7 @@ if (! empty($conf->global->PRODUIT_MULTIPRICES)) print ''; print ''; } - + print '
'.$langs->trans("PriceByQuantityRange").' '.$i.''.$langs->trans("HT").'
'; } else { print $langs->trans("No"); @@ -422,17 +500,17 @@ else print price($object->price_min).' '.$langs->trans($object->price_base_type); } print '
'.$langs->trans("PriceByQuantity"); if($object->prices_by_qty[0] == 0) { print ' '.$langs->trans("Activate"); } print ''; - - if ($object->prices_by_qty[0] == 1) + + if($object->prices_by_qty[0] == 1) { print ''; print ''; @@ -442,7 +520,7 @@ else print ''; print ''; print ''; - foreach ($object->prices_by_qty_list[0] as $ii=> $prices) + 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 ''; @@ -525,7 +603,7 @@ if (! $action || $action == 'delete') if ($user->rights->produit->creer || $user->rights->service->creer) { - print ''.$langs->trans("UpdatePrice").''; + print ''; } print "\n\n"; @@ -671,6 +749,7 @@ $sql.= " AND p.entity IN (".getEntity('productprice', 1).")"; $sql.= " AND p.fk_user_author = u.rowid"; if (! empty($socid) && ! empty($conf->global->PRODUIT_MULTIPRICES)) $sql.= " AND p.price_level = ".$soc->price_level; $sql.= " ORDER BY p.date_price DESC, p.price_level ASC"; +//$sql .= $db->plimit(); dol_syslog("sql=".$sql); $result = $db->query($sql); @@ -724,7 +803,7 @@ if ($result) { $objp = $db->fetch_object($result); $var=!$var; - print ""; + print ""; // Date print ""; @@ -777,6 +856,378 @@ else dol_print_error($db); } +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_product' => $object->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 ''; + print ''; + print ''; + print ''; + print '
'.$langs->trans("Discount").' 
".dol_print_date($db->jdate($objp->dp),"dayhour")."
'; + print ''; + print ''; + print ''; + print ''; + + // VAT + print ''; + + // Price base + print ''; + print ''; + print ''; + + // Price + print ''; + + // Price minimum + print ''; + + // Update all child soc + print ''; + print ''; + print ''; + + print '
' . $langs->trans ( 'ThirdParty' ) . ''; + print $form->select_company ( '', 'socid', 's.rowid NOT IN (SELECT fk_soc FROM ' . MAIN_DB_PREFIX . 'product_customer_price)', 1 ); + print '
' . $langs->trans ( "VATRate" ) . ''; + print $form->load_tva ( "tva_tx", $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr ); + print '
'; + print $langs->trans ( 'PriceBase' ); + print ''; + print $form->select_PriceBaseType ( $object->price_base_type, "price_base_type" ); + print '
'; + $text = $langs->trans ( 'SellingPrice' ); + print $form->textwithpicto ( $text, $langs->trans ( "PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT ), 1, 1 ); + print ''; + if ($object->price_base_type == 'TTC') { + print ''; + } else { + print ''; + } + print '
'; + $text = $langs->trans ( 'MinPrice' ); + print $form->textwithpicto ( $text, $langs->trans ( "PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT ), 1, 1 ); + if ($object->price_base_type == 'TTC') { + print ''; + } else { + print ''; + } + print '
'; + print $langs->trans ( 'ForceUpdateChildPriceSoc' ); + print ''; + print ''; + print '
'; + + print '

 '; + print '
'; + + print '
'; + } 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 '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + $staticsoc = new Societe ( $db ); + $staticsoc->fetch ( $prodcustprice->fk_soc ); + print ""; + print ''; + + // VAT + print ''; + + // Price base + print ''; + print ''; + print ''; + + // Price + print ''; + + // Price minimum + print ''; + + // Update all child soc + print ''; + print ''; + print ''; + + print '
' . $langs->trans ( 'ThirdParty' ) . '" . $staticsoc->getNomUrl ( 1 ) . "
' . $langs->trans ( "VATRate" ) . ''; + print $form->load_tva ( "tva_tx", $prodcustprice->tva_tx, $mysoc, '', $object->id, $prodcustprice->recuperableonly ); + print '
'; + print $langs->trans ( 'PriceBase' ); + print ''; + print $form->select_PriceBaseType ( $prodcustprice->price_base_type, "price_base_type" ); + print '
'; + $text = $langs->trans ( 'SellingPrice' ); + print $form->textwithpicto ( $text, $langs->trans ( "PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT ), 1, 1 ); + print ''; + if ($prodcustprice->price_base_type == 'TTC') { + print ''; + } else { + print ''; + } + print '
'; + $text = $langs->trans ( 'MinPrice' ); + print $form->textwithpicto ( $text, $langs->trans ( "PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT ), 1, 1 ); + if ($prodcustprice->price_base_type == 'TTC') { + print ''; + } else { + print ''; + } + print '
'; + print $langs->trans ( 'ForceUpdateChildPriceSoc' ); + print ''; + print ''; + print '
'; + + print '

 '; + print '
'; + + print '
'; + } elseif ($action=='showlog_customer_price') { + + + $filter = array ( + 't.fk_product' => $object->id, + 't.fk_soc'=> GETPOST('socid','int') + ); + + // 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') . '&id=' . $object->id; + + print_barre_liste ( $langs->trans ( 'PriceByCustomerLog' ), $page, $_SERVEUR ['PHP_SELF'], $option, $sortfield, $sortorder, '', count ( $prodcustprice->lines ), $nbtotalofrecords ); + + if (count ( $prodcustprice->lines ) > 0) { + + print '
'; + print ''; + + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + $var = True; + + foreach ( $prodcustprice->lines as $line ) { + + print ""; + // Date + $staticsoc = new Societe ( $db ); + $staticsoc->fetch ( $line->fk_soc ); + + print ""; + print ""; + + print '"; + print '"; + print '"; + print '"; + print ''; + print ''; + + // User + $userstatic=new User($db); + $userstatic->fetch($line->fk_user); + print ''; + + + + } + print "
' . $langs->trans ( "ThirdParty" ) . '' . $langs->trans ( "AppliedPricesFrom" ) . '' . $langs->trans ( "PriceBase" ) . '' . $langs->trans ( "VAT" ) . '' . $langs->trans ( "HT" ) . '' . $langs->trans ( "TTC" ) . '' . $langs->trans ( "MinPrice" ) . ' ' . $langs->trans ( "HT" ) . '' . $langs->trans ( "MinPrice" ) . ' ' . $langs->trans ( "TTC" ) . '' . $langs->trans ( "ChangedBy" ) . ' 
" . $staticsoc->getNomUrl ( 1 ) . "" . dol_print_date ( $line->datec, "dayhour" ) . "' . $langs->trans ( $line->price_base_type ) . "' . vatrate ( $line->tva_tx, true, $line->recuperableonly ) . "' . price ( $line->price ) . "' . price ( $line->price_ttc ) . "' . price ( $line->price_min ) . '' . price ( $line->price_min_ttc ) . ''; + print $userstatic->getLoginUrl(1); + print '
"; + } else { + print $langs->trans ( 'None' ); + + + } + + print "\n" . '
' . "\n"; + print ''; + print "\n

\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 ''; + print ''; + + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print ''; + print ''; + print ''; + // Print the search button + print ''; + print ''; + + $var = True; + + foreach ( $prodcustprice->lines as $line ) { + + print ""; + // Date + $staticsoc = new Societe ( $db ); + $staticsoc->fetch ( $line->fk_soc ); + + print ""; + print ""; + + print '"; + print '"; + print '"; + print '"; + print ''; + print ''; + + // User + $userstatic=new User($db); + $userstatic->fetch($line->fk_user); + print ''; + + + // Todo Edit or delete button + // Action + if ($user->rights->produit->supprimer || $user->rights->service->supprimer) { + print ''; + } + + print "\n"; + } + print "
' . $langs->trans ( "ThirdParty" ) . '' . $langs->trans ( "AppliedPricesFrom" ) . '' . $langs->trans ( "PriceBase" ) . '' . $langs->trans ( "VAT" ) . '' . $langs->trans ( "HT" ) . '' . $langs->trans ( "TTC" ) . '' . $langs->trans ( "MinPrice" ) . ' ' . $langs->trans ( "HT" ) . '' . $langs->trans ( "MinPrice" ) . ' ' . $langs->trans ( "TTC" ) . '' . $langs->trans ( "ChangedBy" ) . ' 
 '; + print ''; + print '
" . $staticsoc->getNomUrl ( 1 ) . "" . dol_print_date ( $line->datec, "dayhour" ) . "' . $langs->trans ( $line->price_base_type ) . "' . vatrate ( $line->tva_tx, true, $line->recuperableonly ) . "' . price ( $line->price ) . "' . price ( $line->price_ttc ) . "' . price ( $line->price_min ) . '' . price ( $line->price_min_ttc ) . ''; + print $userstatic->getLoginUrl(1); + print ''; + print 'id . '&lineid=' . $line->id . '">'; + print img_delete (); + print ''; + print 'id . '&lineid=' . $line->id . '">'; + print img_edit (); + print ''; + print 'id . '&socid=' . $line->fk_soc . '">'; + print img_info (); + print ''; + print '
"; + + print "
"; + } else { + print $langs->trans ( 'None' ); + } + + /* ************************************************************************** */ + /* */ + /* Barre d'action */ + /* */ + /* ************************************************************************** */ + + print "\n" . '
' . "\n"; + + if ($user->rights->produit->creer || $user->rights->service->creer) { + print ''; + } + print "\n

\n"; + } +} + + llxFooter(); $db->close(); diff --git a/htdocs/societe/price.php b/htdocs/societe/price.php new file mode 100644 index 00000000000..7cd8d9123cc --- /dev/null +++ b/htdocs/societe/price.php @@ -0,0 +1,587 @@ + + * Copyright (C) 2004-2012 Laurent Destailleur + * Copyright (C) 2005 Eric Seigne + * Copyright (C) 2005-2013 Regis Houssin + * Copyright (C) 2006 Andre Cianfarani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/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 ''; + +print ''; + +if (! empty($conf->global->SOCIETE_USEPREFIX)) // Old not used prefix field +{ + print ''; +} + +if ($soc->client) +{ + print ''; +} + +if ($soc->fournisseur) +{ + print ''; +} + +if (! empty($conf->barcode->enabled)) +{ + print ''; +} + +print ""; + +// Zip / Town +print '"; +print '"; + +// Country +if ($soc->country) { + print ''; +} + +// EMail +print ''; + +// Web +print ''; + +// Phone / Fax +print ''; +print ''; + +print '
'.$langs->trans("ThirdPartyName").''; +print $form->showrefnav($soc,'socid','',($user->societe_id?0:1),'rowid','nom'); +print '
'.$langs->trans('Prefix').''.$soc->prefix_comm.'
'; + print $langs->trans('CustomerCode').''; + print $soc->code_client; + if ($soc->check_codeclient() <> 0) print ' ('.$langs->trans("WrongCustomerCode").')'; + print '
'; + print $langs->trans('SupplierCode').''; + print $soc->code_fournisseur; + if ($soc->check_codefournisseur() <> 0) print ' ('.$langs->trans("WrongSupplierCode").')'; + print '
'.$langs->trans('Gencod').''.$soc->barcode.'
".$langs->trans('Address').""; +dol_print_address($soc->address, 'gmap', 'thirdparty', $soc->id); +print "
'.$langs->trans('Zip').''.$soc->zip."'.$langs->trans('Town').''.$soc->town."
'.$langs->trans('Country').''; + $img=picto_from_langcode($soc->country_code); + print ($img?$img.' ':''); + print $soc->country; + print '
'.$langs->trans('EMail').''; +print dol_print_email($soc->email,0,$soc->id,'AC_EMAIL'); +print '
'.$langs->trans('Web').''; +print dol_print_url($soc->url); +print '
'.$langs->trans('Phone').''.dol_print_phone($soc->tel,$soc->country_code,0,$soc->id,'AC_TEL').''.$langs->trans('Fax').''.dol_print_phone($soc->fax,$soc->country_code,0,$soc->id,'AC_FAX').'
'; + +print ''; + + + + +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 '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + // VAT + print ''; + + // Price base + print ''; + print ''; + print ''; + + // Price + print ''; + + // Price minimum + print ''; + + // Update all child soc + print ''; + print ''; + print ''; + + print '
' . $langs->trans ( 'Product' ) . ''; + print $form->select_produits('','prodid','',0); + print '
' . $langs->trans ( "VATRate" ) . ''; + print $form->load_tva ( "tva_tx", $object->tva_tx, $mysoc, '', $object->id, $object->tva_npr ); + print '
'; + print $langs->trans ( 'PriceBase' ); + print ''; + print $form->select_PriceBaseType ( $object->price_base_type, "price_base_type" ); + print '
'; + $text = $langs->trans ( 'SellingPrice' ); + print $form->textwithpicto ( $text, $langs->trans ( "PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT ), 1, 1 ); + print ''; + if ($object->price_base_type == 'TTC') { + print ''; + } else { + print ''; + } + print '
'; + $text = $langs->trans ( 'MinPrice' ); + print $form->textwithpicto ( $text, $langs->trans ( "PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT ), 1, 1 ); + if ($object->price_base_type == 'TTC') { + print ''; + } else { + print ''; + } + print '
'; + print $langs->trans ( 'ForceUpdateChildPriceSoc' ); + print ''; + print ''; + print '
'; + + print '

 '; + print '
'; + + print '
'; + } 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 '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + $staticprod = new Product ( $db ); + $staticprod->fetch ( $prodcustprice->fk_product ); + print ""; + print ''; + + // VAT + print ''; + + // Price base + print ''; + print ''; + print ''; + + // Price + print ''; + + // Price minimum + print ''; + + // Update all child soc + print ''; + print ''; + print ''; + + print '
' . $langs->trans ( 'Product' ) . '" . $staticprod->getNomUrl ( 1 ) . "
' . $langs->trans ( "VATRate" ) . ''; + print $form->load_tva ( "tva_tx", $prodcustprice->tva_tx, $mysoc, '', $staticprod->id, $prodcustprice->recuperableonly ); + print '
'; + print $langs->trans ( 'PriceBase' ); + print ''; + print $form->select_PriceBaseType ( $prodcustprice->price_base_type, "price_base_type" ); + print '
'; + $text = $langs->trans ( 'SellingPrice' ); + print $form->textwithpicto ( $text, $langs->trans ( "PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT ), 1, 1 ); + print ''; + if ($prodcustprice->price_base_type == 'TTC') { + print ''; + } else { + print ''; + } + print '
'; + $text = $langs->trans ( 'MinPrice' ); + print $form->textwithpicto ( $text, $langs->trans ( "PrecisionUnitIsLimitedToXDecimals", $conf->global->MAIN_MAX_DECIMALS_UNIT ), 1, 1 ); + if ($prodcustprice->price_base_type == 'TTC') { + print ''; + } else { + print ''; + } + print '
'; + print $langs->trans ( 'ForceUpdateChildPriceSoc' ); + print ''; + print ''; + print '
'; + + print '

 '; + print '
'; + + print '
'; + } 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 '
'; + print ''; + + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + $var = True; + + foreach ( $prodcustprice->lines as $line ) { + + print ""; + $staticprod = new Product ( $db ); + $staticprod->fetch ( $line->fk_product ); + + print ""; + print ""; + + print '"; + print '"; + print '"; + print '"; + print ''; + print ''; + + // User + $userstatic=new User($db); + $userstatic->fetch($line->fk_user); + print ''; + + + + } + print "
' . $langs->trans ( "Product" ) . '' . $langs->trans ( "AppliedPricesFrom" ) . '' . $langs->trans ( "PriceBase" ) . '' . $langs->trans ( "VAT" ) . '' . $langs->trans ( "HT" ) . '' . $langs->trans ( "TTC" ) . '' . $langs->trans ( "MinPrice" ) . ' ' . $langs->trans ( "HT" ) . '' . $langs->trans ( "MinPrice" ) . ' ' . $langs->trans ( "TTC" ) . '' . $langs->trans ( "ChangedBy" ) . ' 
" . $staticprod->getNomUrl ( 1 ) . "" . dol_print_date ( $line->datec, "dayhour" ) . "' . $langs->trans ( $line->price_base_type ) . "' . vatrate ( $line->tva_tx, true, $line->recuperableonly ) . "' . price ( $line->price ) . "' . price ( $line->price_ttc ) . "' . price ( $line->price_min ) . '' . price ( $line->price_min_ttc ) . ''; + print $userstatic->getLoginUrl(1); + print '
"; + } else { + print $langs->trans ( 'None' ); + + + } + + print "\n" . '
' . "\n"; + print ''; + print "\n

\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 ''; + print ''; + + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print ''; + print ''; + print ''; + // Print the search button + print ''; + print ''; + + $var = True; + + foreach ( $prodcustprice->lines as $line ) { + + print ""; + + $staticprod = new Product ( $db ); + $staticprod->fetch ( $line->fk_product ); + + print ""; + print ""; + + print '"; + print '"; + print '"; + print '"; + print ''; + print ''; + + // User + $userstatic=new User($db); + $userstatic->fetch($line->fk_user); + print ''; + + + // Todo Edit or delete button + // Action + if ($user->rights->produit->creer || $user->rights->service->creer) { + print ''; + } + + print "\n"; + } + print "
' . $langs->trans ( "Product" ) . '' . $langs->trans ( "AppliedPricesFrom" ) . '' . $langs->trans ( "PriceBase" ) . '' . $langs->trans ( "VAT" ) . '' . $langs->trans ( "HT" ) . '' . $langs->trans ( "TTC" ) . '' . $langs->trans ( "MinPrice" ) . ' ' . $langs->trans ( "HT" ) . '' . $langs->trans ( "MinPrice" ) . ' ' . $langs->trans ( "TTC" ) . '' . $langs->trans ( "ChangedBy" ) . ' 
 '; + print ''; + print '
" . $staticprod->getNomUrl ( 1 ) . "" . dol_print_date ( $line->datec, "dayhour" ) . "' . $langs->trans ( $line->price_base_type ) . "' . vatrate ( $line->tva_tx, true, $line->recuperableonly ) . "' . price ( $line->price ) . "' . price ( $line->price_ttc ) . "' . price ( $line->price_min ) . '' . price ( $line->price_min_ttc ) . ''; + print $userstatic->getLoginUrl(1); + print ''; + print 'id . '&lineid=' . $line->id . '">'; + print img_delete (); + print ''; + print 'id . '&lineid=' . $line->id . '">'; + print img_edit (); + print ''; + print 'id . '&prodid=' . $line->fk_product . '">'; + print img_info (); + print ''; + print '
"; + + print "
"; + } else { + print $langs->trans ( 'None' ); + } + + /* ************************************************************************** */ + /* */ + /* Barre d'action */ + /* */ + /* ************************************************************************** */ + + print "\n" . '
' . "\n"; + + if ($user->rights->produit->creer || $user->rights->service->creer) { + print ''; + } + print "\n

\n"; + } +} + + +llxFooter(); + +$db->close(); +?>