%sTVA sur d
RulesVATIn=- Pour les services, le rapport inclut les TVA des réglements effectivement reçus ou émis en se basant sur la date du réglement.
- Pour les biens matériels, il inclut les TVA des factures en se basant sur la date de validation de la facture.
RulesVATDue=- Pour les services, le rapport inclut les TVA des factures dues, payées ou non en se basant sur la date de validation de ces factures.
- Pour les biens matériels, il inclut les TVA des factures en se basant sur la date de validation de la facture.
OptionVatInfoModuleComptabilite=Remarque : Pour les biens matériels, il faudrait utiliser la date de livraison pour être plus juste.
-PercentOfInvoice=%%/facture
\ No newline at end of file
+PercentOfInvoice=%%/facture
+OrderStats=Statistiques sur les commandes
\ No newline at end of file
diff --git a/htdocs/langs/fr_FR/products.lang b/htdocs/langs/fr_FR/products.lang
index 8a8e4a86d40..581593c4d03 100644
--- a/htdocs/langs/fr_FR/products.lang
+++ b/htdocs/langs/fr_FR/products.lang
@@ -55,6 +55,8 @@ SellingPrice=Prix de vente
PublicPrice=Prix public
CurrentPrice=Prix actuel
NewPrice=Nouveau prix
+MinPrice=Prix de vente min.
+CantBeLessThanMinPrice=Le prix de vente ne doit pas être inférieur au minimum pour ce produit (%s HT)
ContractStatus=État du contrat
ContractStatusClosed=Cloturé
ContractStatusRunning=En service
diff --git a/htdocs/lib/functions.lib.php b/htdocs/lib/functions.lib.php
index 887a2984d4b..eda09d7ba4c 100644
--- a/htdocs/lib/functions.lib.php
+++ b/htdocs/lib/functions.lib.php
@@ -1964,14 +1964,16 @@ function vatrate($rate,$addpercent=false,$info_bits=0)
* \param html Type de formatage, html ou pas (par defaut)
* \param outlangs Objet langs pour formatage text
* \param trunc 1=Tronque affichage si trop de decimales,0=Force le non troncage
- * \param nbdecimal Nbre decimals minimum.
+ * \param rounding Nbre decimals minimum.
* \return string Chaine avec montant formate
* \seealso price2num Revert function of price
*/
-function price($amount, $html=0, $outlangs='', $trunc=1, $nbdecimal=2)
+function price($amount, $html=0, $outlangs='', $trunc=1, $rounding=2)
{
global $langs,$conf;
+ $nbdecimal=$rounding;
+
// Output separators by default (french)
$dec=','; $thousand=' ';
@@ -2019,7 +2021,7 @@ function price($amount, $html=0, $outlangs='', $trunc=1, $nbdecimal=2)
}
/**
- * \brief Fonction qui retourne un numerique conforme PHP et SQL, depuis un montant au
+ * \brief Fonction qui retourne un numerique conforme SQL, depuis un montant au
* format utilisateur.
* \remarks Fonction a appeler sur montants saisis avant un insert en base
* \param amount Montant a formater
@@ -2030,28 +2032,33 @@ function price($amount, $html=0, $outlangs='', $trunc=1, $nbdecimal=2)
* \return string Montant au format numerique PHP et SQL (Exemple: '99.99999')
* \seealso price Fonction inverse de price2num
*/
-function price2num($amount,$rounding='')
+function price2num($amount,$rounding='',$alreadysqlnb=-1)
{
global $langs,$conf;
- // Round PHP function does not allow number like '1,234.5'
+ // Round PHP function does not allow number like '1,234.5' nor '1.234,5' nor '1 234,5'
// Numbers must be '1234.5'
// Decimal delimiter for database SQL request must be '.'
$dec=','; $thousand=' ';
if ($langs->trans("SeparatorDecimal") != "SeparatorDecimal") $dec=$langs->trans("SeparatorDecimal");
if ($langs->trans("SeparatorThousand")!= "SeparatorThousand") $thousand=$langs->trans("SeparatorThousand");
-
- if ($thousand != ',' && $thousand != '.') $amount=str_replace(',','.',$amount); // To accept 2 notations for french users
- $amount=str_replace(' ','',$amount); // To avoid spaces
- $amount=str_replace($thousand,'',$amount); // Replace of thousand before replace of dec to avoid pb if thousand is .
- $amount=str_replace($dec,'.',$amount);
+
+ if ($alreadysqlnb != 1) // If not a PHP number or unknown, we change format
+ {
+ if ($thousand != ',' && $thousand != '.') $amount=str_replace(',','.',$amount); // To accept 2 notations for french users
+ $amount=str_replace(' ','',$amount); // To avoid spaces
+ $amount=str_replace($thousand,'',$amount); // Replace of thousand before replace of dec to avoid pb if thousand is .
+ $amount=str_replace($dec,'.',$amount);
+ }
if ($rounding)
{
if ($rounding == 'MU') $amount = round($amount,$conf->global->MAIN_MAX_DECIMALS_UNIT);
elseif ($rounding == 'MT') $amount = round($amount,$conf->global->MAIN_MAX_DECIMALS_TOT);
elseif ($rounding == 'MS') $amount = round($amount,$conf->global->MAIN_MAX_DECIMALS_SHOWN);
else $amount='ErrorBadParameterProvidedToFunction';
+ // Always make replace because each math function (like round) replace
+ // with local values and we want a number that has a SQL string format x.y
if ($thousand != ',' && $thousand != '.') $amount=str_replace(',','.',$amount); // To accept 2 notations for french users
$amount=str_replace(' ','',$amount); // To avoid spaces
$amount=str_replace($thousand,'',$amount); // Replace of thousand before replace of dec to avoid pb if thousand is .
@@ -3059,4 +3066,59 @@ function dol_sort_array($array, $index, $order='asc', $natsort, $case_sensitive)
return $array;
}
+/**
+ * \brief Test if a folder is empty
+ * \return true is empty or non-existing, false if it contains files
+ */
+function is_emtpy_folder($folder){
+ if(is_dir($folder) ){
+ $handle = opendir($folder);
+ while( (gettype( $name = readdir($handle)) != "boolean")){
+ $name_array[] = $name;
+ }
+ foreach($name_array as $temp)
+ $folder_content .= $temp;
+
+ if($folder_content == "...")
+ return true;
+ else
+ return false;
+
+ closedir($handle);
+ }
+ else
+ return true; // Le répertoire n'existe pas
+}
+
+/**
+ * \brief Return an html table from an array
+ */
+function array2table($data,$tableMarkup=1,$tableoptions='',$troptions='',$tdoptions=''){
+ $text='' ;
+ if($tableMarkup) $text = '' ;
+ foreach($data as $key => $item){
+ if(is_array($item)){
+ $text.=array2tr($item,$troptions,$tdoptions) ;
+ } else {
+ $text.= '' ;
+ $text.= '| '.$key.' | ' ;
+ $text.= ''.$item.' | ' ;
+ $text.= '
' ;
+ }
+ }
+ if($tableMarkup) $text.= '
' ;
+ return $text ;
+}
+
+/**
+ * \brief Return lines of an html table from an array
+ */
+function array2tr($data,$troptions='',$tdoptions=''){
+ $text = '' ;
+ foreach($data as $key => $item){
+ $text.= '| '.$item.' | ' ;
+ }
+ $text.= '
' ;
+ return $text ;
+}
?>
\ No newline at end of file
diff --git a/htdocs/product.class.php b/htdocs/product.class.php
index 60effaced27..4886f2cff05 100644
--- a/htdocs/product.class.php
+++ b/htdocs/product.class.php
@@ -50,6 +50,8 @@ class Product extends CommonObject
//! Prix de vente
var $price; // Price without tax
var $price_ttc; // Price with tax
+ var $price_min;
+ var $price_min_ttc;
//! Base de prix (ttc ou ht)
var $price_base_type;
//! Tableau des prix multiples
@@ -155,6 +157,7 @@ class Product extends CommonObject
*/
function create($user)
{
+ global $conf ;
$this->errno = 0;
// Clean parameters
@@ -162,10 +165,13 @@ class Product extends CommonObject
$this->libelle = trim($this->libelle);
if ($this->tva_tx=='') $this->tva_tx = 0;
if ($this->price=='') $this->price = 0;
+ if ($this->price_min=='') $this->price_min = 0;
if ($this->status=='') $this->status = 0;
$price_ht=0;
$price_ttc=0;
+ $price_min_ht=0;
+ $price_min_ttc=0;
if ($this->price_base_type == 'TTC' && $this->price_ttc > 0)
{
$price_ttc = price2num($this->price_ttc,'MU');
@@ -176,6 +182,17 @@ class Product extends CommonObject
$price_ht = price2num($this->price,'MU');
$price_ttc = price2num($this->price * (1 + ($this->tva_tx / 100)),'MU');
}
+
+ if (($this->price_min_ttc > 0)&&($this->price_base_type == 'TTC'))
+ {
+ $price_min_ttc = price2num($this->price_min_ttc,'MU');
+ $price_min_ht = price2num($this->price_min_ttc / (1 + ($this->tva_tx / 100)),'MU');
+ }
+ if (($this->price_min > 0)&&($this->price_base_type != 'TTC'))
+ {
+ $price_min_ht = price2num($this->price_min,'MU');
+ $price_min_ttc = price2num($this->price_min * (1 + ($this->tva_tx / 100)),'MU');
+ }
// Check parameters
if (empty($this->libelle))
@@ -203,10 +220,13 @@ class Product extends CommonObject
$sql = "INSERT INTO ".MAIN_DB_PREFIX."product";
$sql.= " (datec, ";
if ($this->ref) $sql.= "ref, ";
+ $sql.= "price_min, price_min_ttc, ";
$sql.= "label, ";
$sql.= "fk_user_author, fk_product_type, price, price_ttc, price_base_type, canvas)";
$sql.= " VALUES (".$this->db->idate(mktime()).", ";
if ($this->ref) $sql.= "'".$this->ref."',";
+ $sql.= price2num($price_min_ht).",";
+ $sql.= price2num($price_min_ttc).",";
$sql.= " ".($this->libelle?"'".addslashes($this->libelle)."'":"null").",";
$sql.= $user->id.",";
$sql.= " ".$this->type.",";
@@ -226,7 +246,9 @@ class Product extends CommonObject
$this->id = $id;
$this->price = $price_ht;
$this->price_ttc = $price_ttc;
-
+ $this->price_min = $price_min_ht;
+ $this->price_min_ttc = $price_min_ttc;
+
$result = $this->_log_price($user);
if ($result > 0)
{
@@ -487,6 +509,10 @@ class Product extends CommonObject
$sqlb = "DELETE from ".MAIN_DB_PREFIX."product_price";
$sqlb.= " WHERE fk_product = ".$id;
$resultb = $this->db->query($sqlb);
+
+ $sqlb = "DELETE from ".MAIN_DB_PREFIX."product_price_min";
+ $sqlb.= " WHERE fk_product = ".$id;
+ $resultb = $this->db->query($sqlb);
$sqlc = "DELETE from ".MAIN_DB_PREFIX."product_det";
$sqlc.= " WHERE fk_product = ".$id;
@@ -655,9 +681,10 @@ class Product extends CommonObject
if (strlen(trim($this->price)) > 0 )
{
// On ajoute nouveau tarif
- $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price(date_price,fk_product,fk_user_author,price,price_ttc,price_base_type,envente,tva_tx) ";
- $sql .= " VALUES(".$this->db->idate(mktime()).",".$this->id.",".$user->id.",".$this->price.",".$this->price_ttc.",'".$this->price_base_type."',".$this->status.",".$this->tva_tx;
- $sql .= ")";
+ $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price(date_price,fk_product,fk_user_author,price,price_ttc,price_base_type,envente,tva_tx,price_min,price_min_ttc) ";
+ $sql.= " VALUES(".$this->db->idate(mktime()).",".$this->id.",".$user->id.",".$this->price.",".$this->price_ttc.",'".$this->price_base_type."',".$this->status.",".$this->tva_tx;
+ $sql.= ",".$this->price_min.",".$this->price_min_ttc;
+ $sql.= ")";
if (! $this->db->query($sql) )
$queryError = true;
}
@@ -671,22 +698,28 @@ class Product extends CommonObject
}
else
{
+ $queryError = false;
+
// On ajoute nouveau tarif
- $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price(date_price,fk_product,fk_user_author,price,price_ttc,price_base_type,envente,tva_tx) ";
- $sql .= " VALUES(".$this->db->idate(mktime()).",".$this->id.",".$user->id.",".$this->price.",".$this->price_ttc.",'".$this->price_base_type."',".$this->status.",".$this->tva_tx;
- $sql .= ")";
+ $sql = "INSERT INTO ".MAIN_DB_PREFIX."product_price(date_price,fk_product,fk_user_author,price,price_ttc,price_base_type,envente,tva_tx,price_min,price_min_ttc) ";
+ $sql.= " VALUES(".$this->db->idate(mktime()).",".$this->id.",".$user->id.",".$this->price.",".$this->price_ttc.",'".$this->price_base_type."',".$this->status.",".$this->tva_tx;
+ $sql.= ",".$this->price_min.",".$this->price_min_ttc;
+ $sql.= ")";
dolibarr_syslog("Product::_log_price sql=".$sql);
$resql=$this->db->query($sql);
- if ($resql)
- {
- return 1;
- }
- else
+ if (!$resql)
+ $queryError = true;
+
+ if($queryError)
{
dolibarr_print_error($this->db);
return -1;
}
+ else
+ return 1;
+
+
}
}
@@ -777,7 +810,7 @@ class Product extends CommonObject
* \param newvat New VAT Rate
* \return int <0 if KO, >0 if OK
*/
- function update_price($id, $newprice, $newpricebase, $user, $newvat='')
+ function update_price($id, $newprice, $newpricebase, $user, $newvat='',$newminprice='')
{
//multiprix
global $conf,$langs;
@@ -792,12 +825,24 @@ class Product extends CommonObject
$price_ttc = price2num($newprice,'MU');
$price = price2num($newprice) / (1 + ($newvat / 100));
$price = price2num($price,'MU');
+
+ if($newminprice!=''){
+ $price_min_ttc = price2num($newminprice,'MU');
+ $price_min = price2num($newminprice) / (1 + ($newvat / 100));
+ $price_min = price2num($price_min,'MU');
+ }
}
else
{
$price = price2num($newprice,'MU');
$price_ttc = price2num($newprice) * (1 + ($newvat / 100));
$price_ttc = price2num($price_ttc,'MU');
+
+ if($newminprice!=''){
+ $price_min = price2num($newminprice,'MU');
+ $price_min_ttc = price2num($newminprice) * (1 + ($newvat / 100));
+ $price_min_ttc = price2num($price_min_ttc,'MU');
+ }
}
// Ne pas mettre de quote sur le num�riques decimaux.
@@ -806,6 +851,8 @@ class Product extends CommonObject
$sql.= " price_base_type='".$newpricebase."',";
$sql.= " price=".$price.",";
$sql.= " price_ttc=".$price_ttc.",";
+ $sql.= " price_min=".$price_min.",";
+ $sql.= " price_min_ttc=".$price_min_ttc.",";
$sql.= " tva_tx='".price2num($newvat)."'";
$sql.= " WHERE rowid = " . $id;
@@ -815,6 +862,8 @@ class Product extends CommonObject
{
$this->price = $price;
$this->price_ttc = $price_ttc;
+ $this->price_min = $price_min;
+ $this->price_min_ttc = $price_min_ttc;
$this->price_base_type = $newpricebase;
$this->tva_tx = $newvat;
@@ -861,7 +910,7 @@ class Product extends CommonObject
return -1;
}
- $sql = "SELECT rowid, ref, label, description, note, price, price_ttc, price_base_type, tva_tx, envente,";
+ $sql = "SELECT rowid, ref, label, description, note, price, price_ttc, price_min, price_min_ttc, price_base_type, tva_tx, envente,";
$sql.= " nbvente, fk_product_type, duration, seuil_stock_alerte,canvas,";
$sql.= " stock_commande, stock_loc, weight, weight_units, volume, volume_units, barcode, fk_barcode_type";
$sql.= " FROM ".MAIN_DB_PREFIX."product";
@@ -881,6 +930,8 @@ class Product extends CommonObject
$this->note = $result["note"];
$this->price = $result["price"];
$this->price_ttc = $result["price_ttc"];
+ $this->price_min = $result["price_min"];
+ $this->price_min_ttc = $result["price_min_ttc"];
$this->price_base_type = $result["price_base_type"];
$this->tva_tx = $result["tva_tx"];
$this->type = $result["fk_product_type"];
diff --git a/htdocs/product/fiche.php b/htdocs/product/fiche.php
index 3e64ac6e98c..636b218cd37 100644
--- a/htdocs/product/fiche.php
+++ b/htdocs/product/fiche.php
@@ -88,6 +88,8 @@ if ($_POST["action"] == 'add' && $user->rights->produit->creer)
$product->price_base_type = $_POST["price_base_type"];
if ($product->price_base_type == 'TTC') $product->price_ttc = $_POST["price"];
else $product->price = $_POST["price"];
+ if ($product->price_base_type == 'TTC') $product->price_min_ttc = $_POST["price_min"];
+ else $product->price_min = $_POST["price_min"];
$product->tva_tx = $_POST["tva_tx"];
$product->type = $_POST["type"];
$product->status = $_POST["statut"];
@@ -687,6 +689,11 @@ if ($_GET["action"] == 'create' && $user->rights->produit->creer)
print '';
}
+ // MIN PRICE
+ print '| '.$langs->trans("MinPrice").' | ';
+ print '';
+ print ' |
';
+
// VAT
print '| '.$langs->trans("VATRate").' | ';
print $html->select_tva("tva_tx",$conf->defaulttx,$mysoc,'');
@@ -870,6 +877,18 @@ if ($_GET["id"] || $_GET["ref"])
}
print ' |
';
}
+
+ // Prix mini
+ print '| '.$langs->trans("MinPrice").' | ';
+ if ($product->price_base_type == 'TTC')
+ {
+ print price($product->price_min_ttc).' '.$langs->trans($product->price_base_type);
+ }
+ else
+ {
+ print price($product->price_min).' '.$langs->trans($product->price_base_type);
+ }
+ print ' |
';
// TVA
print '| '.$langs->trans("VATRate").' | '.vatrate($product->tva_tx,true).' |
';
diff --git a/htdocs/product/price.php b/htdocs/product/price.php
index 4648da25d7e..b7b7f754d25 100644
--- a/htdocs/product/price.php
+++ b/htdocs/product/price.php
@@ -91,7 +91,10 @@ if ($_POST["action"] == 'update_price' &&
$newvat=$_POST["tva_tx"];
}
- if ($product->update_price($product->id, $newprice, $newpricebase, $user, $newvat) > 0)
+ $newprice_min = '' ;
+ $newprice_min = price2num($_POST["price_min"],'MU');
+
+ if ($product->update_price($product->id, $newprice, $newpricebase, $user, $newvat,$newprice_min) > 0)
{
$_GET["action"] = '';
$mesg = $langs->trans("RecordSaved");
@@ -175,6 +178,18 @@ else
}
}
+// Prix minimum
+print '| '.$langs->trans("MinPrice").' | ';
+if ($product->price_base_type == 'TTC')
+{
+ print price($product->price_min_ttc).' '.$langs->trans($product->price_base_type);
+}
+else
+{
+ print price($product->price_min).' '.$langs->trans($product->price_base_type);
+}
+print ' |
';
+
// TVA
print '| '.$langs->trans("VATRate").' | '.vatrate($product->tva_tx,true).' |
';
@@ -237,9 +252,23 @@ if ($_GET["action"] == 'edit_price' && $user->rights->produit->creer)
{
print '| '.$langs->trans("VATRate").' | ';
print $html->select_tva("tva_tx",$product->tva_tx,$mysoc,'');
@@ -275,6 +304,19 @@ if ($_GET["action"] == 'edit_price' && $user->rights->produit->creer)
print $html->select_PriceBaseType($product->multiprices_base_type["$i"], "multiprices_base_type_".$i);
print ' | ';
+ print '
| ' ;
+ $text=$langs->trans('MinPrice') ;
+ print $html->textwithhelp($text,$langs->trans("PrecisionUnitIsLimitedToXDecimals",$conf->global->MAIN_MAX_DECIMALS_UNIT),$direction=1,$usehelpcursor=1);
+ if ($product->price_base_type == 'TTC')
+ {
+ print ' | ';
+ }
+ else
+ {
+ print ' | ';
+ }
+ print ' | ';
+
// VAT
print ''.$langs->trans("VATRate").' | ';
print $html->select_tva("tva_tx_".$i,$product->multiprices_tva_tx["$i"],$mysoc,'');
@@ -286,7 +328,6 @@ if ($_GET["action"] == 'edit_price' && $user->rights->produit->creer)
print '';
}
}
-
}
@@ -304,9 +345,10 @@ if($conf->global->PRODUIT_MULTIPRICES)
else
{
$sql = "SELECT p.rowid, p.price, p.price_ttc, p.price_base_type, p.tva_tx,";
+ $sql.= " p.price_min, p.price_min_ttc,";
$sql.= " ".$db->pdate("p.date_price")." as dp, u.rowid as user_id, u.login";
- $sql.= " FROM ".MAIN_DB_PREFIX."product_price as p, ".MAIN_DB_PREFIX."user as u";
- $sql.= " WHERE fk_product = ".$product->id;
+ $sql.= " FROM ".MAIN_DB_PREFIX."user as u, ".MAIN_DB_PREFIX."product_price as p ";
+ $sql.= " WHERE p.fk_product = ".$product->id;
$sql.= " AND p.fk_user_author = u.rowid";
$sql.= " ORDER BY p.date_price DESC";
}
@@ -323,7 +365,7 @@ if ($result)
// Il doit au moins y avoir la ligne de prix initial.
// On l'ajoute donc pour remettre à niveau (pb vieilles versions)
- $product->update_price($product->id, $product->price, 'HT' ,$user);
+ $product->update_price($product->id, $product->price, 'HT' ,$user,$newprice_min);
$result = $db->query($sql) ;
$num = $db->num_rows($result);
@@ -347,6 +389,8 @@ if ($result)
print ' | '.$langs->trans("VAT").' | ';
print ''.$langs->trans("HT").' | ';
print ''.$langs->trans("TTC").' | ';
+ print ''.$langs->trans("MinPrice").' '.$langs->trans("HT").' | ';
+ print ''.$langs->trans("MinPrice").' '.$langs->trans("TTC").' | ';
print ''.$langs->trans("ChangedBy").' | ';
print '
';
@@ -370,6 +414,8 @@ if ($result)
print '