Ver código fonte

FIX The vat rate line used when adding a predefined product was wrong if
there is several vat line with same rate.

Laurent Destailleur 8 anos atrás
pai
commit
f67c967d0b

+ 17 - 15
htdocs/comm/propal/card.php

@@ -731,9 +731,11 @@ if (empty($reshook))
 
 			$db->begin();
 
+            // $tva_tx can be 'x.x (XXX)'
+            
 			// Ecrase $pu par celui du produit
 			// Ecrase $desc par celui du produit
-			// Ecrase $txtva par celui du produit
+			// Ecrase $tva_tx par celui du produit
 			// Replaces $fk_unit with the product unit
 			if (! empty($idprod)) {
 				$prod = new Product($db);
@@ -741,12 +743,10 @@ if (empty($reshook))
 
 				$label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
 
-				// If prices fields are update
+				// Update if prices fields are defined
 				$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
 				$tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
 				if (empty($tva_tx)) $tva_npr=0;
-var_dump($tva_tx);
-exit;
 
 				$pu_ht = $prod->price;
 				$pu_ttc = $prod->price_ttc;
@@ -756,7 +756,7 @@ exit;
 				// On defini prix unitaire
 				if (! empty($conf->global->PRODUIT_MULTIPRICES) && $object->thirdparty->price_level)
 				{
-					$pu_ht = $prod->multiprices[$object->thirdparty->price_level];
+				    $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
 					$pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
 					$price_min = $prod->multiprices_min[$object->thirdparty->price_level];
 					$price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
@@ -777,27 +777,29 @@ exit;
 					$result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
 					if ($result) {
 						if (count($prodcustprice->lines) > 0) {
-							$pu_ht = price($prodcustprice->lines [0]->price);
-							$pu_ttc = price($prodcustprice->lines [0]->price_ttc);
-							$price_base_type = $prodcustprice->lines [0]->price_base_type;
-							$tva_tx = $prodcustprice->lines [0]->tva_tx;
+							$pu_ht = price($prodcustprice->lines[0]->price);
+							$pu_ttc = price($prodcustprice->lines[0]->price_ttc);
+							$price_base_type = $prodcustprice->lines[0]->price_base_type;
+							$tva_tx = $prodcustprice->lines[0]->tva_tx;
 						}
 					}
 				}
 
-				// if price ht is forced (ie: calculated by margin rate and cost price)
+				$tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
+				$tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
+				
+				// if price ht is forced (ie: calculated by margin rate and cost price). TODO Why this ?
 				if (! empty($price_ht)) {
 					$pu_ht = price2num($price_ht, 'MU');
-					$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
+					$pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
 				}
-
 				// On reevalue prix selon taux tva car taux tva transaction peut etre different
 				// de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
-				elseif ($tva_tx != $prod->tva_tx) {
+				elseif ($tmpvat != $tmpprodvat) {
 					if ($price_base_type != 'HT') {
-						$pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU');
+						$pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
 					} else {
-						$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
+						$pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
 					}
 				}
 

+ 2 - 2
htdocs/comm/propal/class/propal.class.php

@@ -413,7 +413,7 @@ class Propal extends CommonObject
         $qty=price2num($qty);
         $pu_ht=price2num($pu_ht);
         $pu_ttc=price2num($pu_ttc);
-        $txtva=price2num($txtva);
+        $txtva=price2num($txtva);               // $txtva can have format '5.0(XXX)' or '5'
         $txlocaltax1=price2num($txlocaltax1);
         $txlocaltax2=price2num($txlocaltax2);
     	$pa_ht=price2num($pa_ht);
@@ -428,7 +428,7 @@ class Propal extends CommonObject
 
         // Check parameters
         if ($type < 0) return -1;
-
+      
         if ($this->statut == self::STATUS_DRAFT)
         {
             $this->db->begin();

+ 83 - 81
htdocs/commande/card.php

@@ -698,7 +698,7 @@ if (empty($reshook))
 
 			// Ecrase $pu par celui du produit
 			// Ecrase $desc par celui du produit
-			// Ecrase $txtva par celui du produit
+			// Ecrase $tva_tx par celui du produit
 			// Ecrase $base_price_type par celui du produit
 			if (! empty($idprod)) {
 				$prod = new Product($db);
@@ -707,103 +707,105 @@ if (empty($reshook))
 				$label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
 
 				// Update if prices fields are defined
-					$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
-					$tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
-					if (empty($tva_tx)) $tva_npr=0;
+				$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
+				$tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
+				if (empty($tva_tx)) $tva_npr=0;
 
-					$pu_ht = $prod->price;
-					$pu_ttc = $prod->price_ttc;
-					$price_min = $prod->price_min;
-					$price_base_type = $prod->price_base_type;
+				$pu_ht = $prod->price;
+				$pu_ttc = $prod->price_ttc;
+				$price_min = $prod->price_min;
+				$price_base_type = $prod->price_base_type;
 
-					// multiprix
-					if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level))
+				// multiprix
+				if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level))
+				{
+					$pu_ht = $prod->multiprices[$object->thirdparty->price_level];
+					$pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
+					$price_min = $prod->multiprices_min[$object->thirdparty->price_level];
+					$price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
+					if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL))  // using this option is a bug. kept for backward compatibility
 					{
-						$pu_ht = $prod->multiprices[$object->thirdparty->price_level];
-						$pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
-						$price_min = $prod->multiprices_min[$object->thirdparty->price_level];
-						$price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
-						if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL))  // using this option is a bug. kept for backward compatibility
-						{
-						  if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) $tva_tx=$prod->multiprices_tva_tx[$object->thirdparty->price_level];
-						  if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) $tva_npr=$prod->multiprices_recuperableonly[$object->thirdparty->price_level];
-						}
+					  if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) $tva_tx=$prod->multiprices_tva_tx[$object->thirdparty->price_level];
+					  if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) $tva_npr=$prod->multiprices_recuperableonly[$object->thirdparty->price_level];
 					}
-					elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES))
-					{
-						require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
+				}
+				elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES))
+				{
+					require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
 
-						$prodcustprice = new Productcustomerprice($db);
+					$prodcustprice = new Productcustomerprice($db);
 
-						$filter = array('t.fk_product' => $prod->id,'t.fk_soc' => $object->thirdparty->id);
+					$filter = array('t.fk_product' => $prod->id,'t.fk_soc' => $object->thirdparty->id);
 
-						$result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
-						if ($result >= 0)
-						{
-							if (count($prodcustprice->lines) > 0)
-							{
-								$pu_ht = price($prodcustprice->lines [0]->price);
-								$pu_ttc = price($prodcustprice->lines [0]->price_ttc);
-								$price_base_type = $prodcustprice->lines [0]->price_base_type;
-								$tva_tx = $prodcustprice->lines [0]->tva_tx;
-							}
-						}
-						else
+					$result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
+					if ($result >= 0)
+					{
+						if (count($prodcustprice->lines) > 0)
 						{
-							setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
+							$pu_ht = price($prodcustprice->lines [0]->price);
+							$pu_ttc = price($prodcustprice->lines [0]->price_ttc);
+							$price_base_type = $prodcustprice->lines [0]->price_base_type;
+							$tva_tx = $prodcustprice->lines [0]->tva_tx;
 						}
 					}
-
-					// if price ht is forced (ie: calculated by margin rate and cost price)
-					if (! empty($price_ht)) {
-						$pu_ht = price2num($price_ht, 'MU');
-						$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
+					else
+					{
+						setEventMessages($prodcustprice->error, $prodcustprice->errors, 'errors');
 					}
+				}
 
-					// On reevalue prix selon taux tva car taux tva transaction peut etre different
-					// de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
-					elseif ($tva_tx != $prod->tva_tx) {
-						if ($price_base_type != 'HT') {
-							$pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU');
-						} else {
-							$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
-						}
+				$tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
+				$tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
+				
+				// if price ht is forced (ie: calculated by margin rate and cost price). TODO Why this ?
+				if (! empty($price_ht)) {
+					$pu_ht = price2num($price_ht, 'MU');
+					$pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
+				}
+				// On reevalue prix selon taux tva car taux tva transaction peut etre different
+				// de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
+				elseif ($tmpvat != $tmpprodvat) {
+					if ($price_base_type != 'HT') {
+						$pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
+					} else {
+						$pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
 					}
+				}
 
-					$desc = '';
+				$desc = '';
 
-					// Define output language
-					if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
-						$outputlangs = $langs;
-						$newlang = '';
-						if (empty($newlang) && GETPOST('lang_id'))
-							$newlang = GETPOST('lang_id');
-						if (empty($newlang))
-							$newlang = $object->thirdparty->default_lang;
-						if (! empty($newlang)) {
-							$outputlangs = new Translate("", $conf);
-							$outputlangs->setDefaultLang($newlang);
-						}
-
-						$desc = (! empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
-					} else {
-						$desc = $prod->description;
+				// Define output language
+				if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
+					$outputlangs = $langs;
+					$newlang = '';
+					if (empty($newlang) && GETPOST('lang_id'))
+						$newlang = GETPOST('lang_id');
+					if (empty($newlang))
+						$newlang = $object->thirdparty->default_lang;
+					if (! empty($newlang)) {
+						$outputlangs = new Translate("", $conf);
+						$outputlangs->setDefaultLang($newlang);
 					}
 
-					$desc = dol_concatdesc($desc, $product_desc);
-
-					// Add custom code and origin country into description
-					if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) {
-						$tmptxt = '(';
-						if (! empty($prod->customcode))
-							$tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
-						if (! empty($prod->customcode) && ! empty($prod->country_code))
-							$tmptxt .= ' - ';
-						if (! empty($prod->country_code))
-							$tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
-						$tmptxt .= ')';
-						$desc = dol_concatdesc($desc, $tmptxt);
-					}
+					$desc = (! empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
+				} else {
+					$desc = $prod->description;
+				}
+
+				$desc = dol_concatdesc($desc, $product_desc);
+
+				// Add custom code and origin country into description
+				if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) {
+					$tmptxt = '(';
+					if (! empty($prod->customcode))
+						$tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
+					if (! empty($prod->customcode) && ! empty($prod->country_code))
+						$tmptxt .= ' - ';
+					if (! empty($prod->country_code))
+						$tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
+					$tmptxt .= ')';
+					$desc = dol_concatdesc($desc, $tmptxt);
+				}
 
 				$type = $prod->type;
 				$fk_unit = $prod->fk_unit;

+ 82 - 79
htdocs/compta/facture.php

@@ -1394,7 +1394,7 @@ if (empty($reshook))
 
 			// Ecrase $pu par celui du produit
 			// Ecrase $desc par celui du produit
-			// Ecrase $txtva par celui du produit
+			// Ecrase $tva_tx par celui du produit
 			// Ecrase $base_price_type par celui du produit
 			// Replaces $fk_unit with the product's
 			if (! empty($idprod))
@@ -1405,102 +1405,105 @@ if (empty($reshook))
 				$label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
 
 				// Update if prices fields are defined
-					$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
-					$tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
-					if (empty($tva_tx)) $tva_npr=0;
+				$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
+				$tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
+				if (empty($tva_tx)) $tva_npr=0;
 
-					$pu_ht = $prod->price;
-					$pu_ttc = $prod->price_ttc;
-					$price_min = $prod->price_min;
-					$price_base_type = $prod->price_base_type;
+				$pu_ht = $prod->price;
+				$pu_ttc = $prod->price_ttc;
+				$price_min = $prod->price_min;
+				$price_base_type = $prod->price_base_type;
 
-					// We define price for product
-					if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level))
+				// We define price for product
+				if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level))
+				{
+					$pu_ht = $prod->multiprices[$object->thirdparty->price_level];
+					$pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
+					$price_min = $prod->multiprices_min[$object->thirdparty->price_level];
+					$price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
+					if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL))  // using this option is a bug. kept for backward compatibility
 					{
-						$pu_ht = $prod->multiprices[$object->thirdparty->price_level];
-						$pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
-						$price_min = $prod->multiprices_min[$object->thirdparty->price_level];
-						$price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
-						if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL))  // using this option is a bug. kept for backward compatibility
-						{
-                            if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) $tva_tx=$prod->multiprices_tva_tx[$object->thirdparty->price_level];
-                            if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) $tva_npr=$prod->multiprices_recuperableonly[$object->thirdparty->price_level];
-							if (empty($tva_tx)) $tva_npr=0;
-						}
+                        if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) $tva_tx=$prod->multiprices_tva_tx[$object->thirdparty->price_level];
+                        if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) $tva_npr=$prod->multiprices_recuperableonly[$object->thirdparty->price_level];
+						if (empty($tva_tx)) $tva_npr=0;
 					}
-					elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES))
-					{
-						require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
+				}
+				elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES))
+				{
+					require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
 
-						$prodcustprice = new Productcustomerprice($db);
+					$prodcustprice = new Productcustomerprice($db);
 
-						$filter = array('t.fk_product' => $prod->id,'t.fk_soc' => $object->thirdparty->id);
+					$filter = array('t.fk_product' => $prod->id,'t.fk_soc' => $object->thirdparty->id);
 
-						$result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
-						if ($result) {
-							if (count($prodcustprice->lines) > 0) {
-								$pu_ht = price($prodcustprice->lines[0]->price);
-								$pu_ttc = price($prodcustprice->lines[0]->price_ttc);
-								$price_base_type = $prodcustprice->lines[0]->price_base_type;
-								$tva_tx = $prodcustprice->lines[0]->tva_tx;
-							}
+					$result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
+					if ($result) {
+						if (count($prodcustprice->lines) > 0) {
+							$pu_ht = price($prodcustprice->lines[0]->price);
+							$pu_ttc = price($prodcustprice->lines[0]->price_ttc);
+							$price_base_type = $prodcustprice->lines[0]->price_base_type;
+							$tva_tx = $prodcustprice->lines[0]->tva_tx;
 						}
 					}
+				}
 
-					// if price ht was forced (ie: from gui when calculated by margin rate and cost price)
-					if (! empty($price_ht))
+				$tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
+				$tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
+			    
+				// if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
+				if (! empty($price_ht))
+				{
+					$pu_ht = price2num($price_ht, 'MU');
+					$pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
+				}
+				// On reevalue prix selon taux tva car taux tva transaction peut etre different
+				// de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
+				elseif ($tmpvat != $tmpprodvat)
+				{
+					if ($price_base_type != 'HT')
 					{
-						$pu_ht = price2num($price_ht, 'MU');
-						$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
+						$pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
 					}
-					// On reevalue prix selon taux tva car taux tva transaction peut etre different
-					// de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
-					elseif ($tva_tx != $prod->tva_tx)
+					else
 					{
-						if ($price_base_type != 'HT')
-						{
-							$pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU');
-						}
-						else
-						{
-							$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
-						}
+						$pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
 					}
+				}
 
-					$desc = '';
+				$desc = '';
 
-					// Define output language
-					if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
-						$outputlangs = $langs;
-						$newlang = '';
-						if (empty($newlang) && GETPOST('lang_id'))
-							$newlang = GETPOST('lang_id');
-						if (empty($newlang))
-							$newlang = $object->thirdparty->default_lang;
-						if (! empty($newlang)) {
-							$outputlangs = new Translate("", $conf);
-							$outputlangs->setDefaultLang($newlang);
-						}
-
-						$desc = (! empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
-					} else {
-						$desc = $prod->description;
+				// Define output language
+				if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
+					$outputlangs = $langs;
+					$newlang = '';
+					if (empty($newlang) && GETPOST('lang_id'))
+						$newlang = GETPOST('lang_id');
+					if (empty($newlang))
+						$newlang = $object->thirdparty->default_lang;
+					if (! empty($newlang)) {
+						$outputlangs = new Translate("", $conf);
+						$outputlangs->setDefaultLang($newlang);
 					}
 
-					$desc = dol_concatdesc($desc, $product_desc);
-
-					// Add custom code and origin country into description
-					if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) {
-						$tmptxt = '(';
-						if (! empty($prod->customcode))
-							$tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
-						if (! empty($prod->customcode) && ! empty($prod->country_code))
-							$tmptxt .= ' - ';
-						if (! empty($prod->country_code))
-							$tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
-						$tmptxt .= ')';
-						$desc = dol_concatdesc($desc, $tmptxt);
-					}
+					$desc = (! empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
+				} else {
+					$desc = $prod->description;
+				}
+
+				$desc = dol_concatdesc($desc, $product_desc);
+
+				// Add custom code and origin country into description
+				if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) {
+					$tmptxt = '(';
+					if (! empty($prod->customcode))
+						$tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
+					if (! empty($prod->customcode) && ! empty($prod->country_code))
+						$tmptxt .= ' - ';
+					if (! empty($prod->country_code))
+						$tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
+					$tmptxt .= ')';
+					$desc = dol_concatdesc($desc, $tmptxt);
+				}
 
 				$type = $prod->type;
 				$fk_unit = $prod->fk_unit;

+ 9 - 6
htdocs/compta/facture/fiche-rec.php

@@ -456,7 +456,7 @@ if (empty($reshook))
 
     	// Ecrase $pu par celui du produit
     	// Ecrase $desc par celui du produit
-    	// Ecrase $txtva par celui du produit
+    	// Ecrase $tva_tx par celui du produit
     	// Ecrase $base_price_type par celui du produit
     	// Replaces $fk_unit with the product's
     	if (! empty($idprod))
@@ -511,23 +511,26 @@ if (empty($reshook))
     			}
     		}
 
-    		// if price ht was forced (ie: from gui when calculated by margin rate and cost price)
+			$tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
+			$tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
+			
+    		// if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
     		if (! empty($price_ht))
     		{
     			$pu_ht = price2num($price_ht, 'MU');
-    			$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
+    			$pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
     		}
     		// On reevalue prix selon taux tva car taux tva transaction peut etre different
     		// de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
-    		elseif ($tva_tx != $prod->tva_tx)
+    		elseif ($tmpvat != $tmpprodvat)
     		{
     			if ($price_base_type != 'HT')
     			{
-    			    $pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU');
+    			    $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
     			}
     			else
     			{
-    			    $pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
+    			    $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
     			}
     		}
 

+ 44 - 19
htdocs/contrat/card.php

@@ -407,21 +407,21 @@ if (empty($reshook))
 		// Set if we used free entry or predefined product
 		$predef='';
 		$product_desc=(GETPOST('dp_desc')?GETPOST('dp_desc'):'');
+		$price_ht = GETPOST('price_ht');
+		$price_ht_devise = GETPOST('multicurrency_price_ht');
 		if (GETPOST('prod_entry_mode') == 'free')
 		{
 			$idprod=0;
-			$price_ht = GETPOST('price_ht');
 			$tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
 		}
 		else
 		{
 			$idprod=GETPOST('idprod', 'int');
-			$price_ht = '';
 			$tva_tx = '';
 		}
 	
 		$qty = GETPOST('qty'.$predef);
-		$remise_percent=GETPOST('remise_percent'.$predef);
+		$remise_percent = GETPOST('remise_percent'.$predef);
 	
 	    if ($qty == '')
 	    {
@@ -455,13 +455,14 @@ if (empty($reshook))
 	
 	        // Ecrase $pu par celui du produit
 	        // Ecrase $desc par celui du produit
-	        // Ecrase $txtva par celui du produit
+	        // Ecrase $tva_tx par celui du produit
 	        // Ecrase $base_price_type par celui du produit
 	        if ($idprod > 0)
 	        {
 	            $prod = new Product($db);
 	            $prod->fetch($idprod);
 	
+	            // Update if prices fields are defined
 	            $tva_tx = get_default_tva($mysoc,$object->thirdparty,$prod->id);
 	            $tva_npr = get_default_npr($mysoc,$object->thirdparty,$prod->id);
 	            if (empty($tva_tx)) $tva_npr=0;
@@ -498,17 +499,20 @@ if (empty($reshook))
 					}
 				}
 	
-	            // On reevalue prix selon taux tva car taux tva transaction peut etre different
+				$tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
+				$tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
+				
+				// On reevalue prix selon taux tva car taux tva transaction peut etre different
 	            // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
-	            if ($tva_tx != $prod->tva_tx)
+	            if ($tmpvat != $tmpprodvat)
 	            {
 	                if ($price_base_type != 'HT')
 	                {
-	                    $pu_ht = price2num($pu_ttc / (1 + ($tva_tx/100)), 'MU');
+	                    $pu_ht = price2num($pu_ttc / (1 + ($tmpvat/100)), 'MU');
 	                }
 	                else
 	              {
-	                    $pu_ttc = price2num($pu_ht * (1 + ($tva_tx/100)), 'MU');
+	                    $pu_ttc = price2num($pu_ht * (1 + ($tmpvat/100)), 'MU');
 	                }
 	            }
 	
@@ -626,7 +630,7 @@ if (empty($reshook))
 	    }
 	}
 	
-	else if ($action == 'updateligne' && $user->rights->contrat->creer && ! GETPOST('cancel'))
+	else if ($action == 'updateline' && $user->rights->contrat->creer && ! GETPOST('cancel'))
 	{
 	    $objectline = new ContratLigne($db);
 	    if ($objectline->fetch(GETPOST('elrowid')))
@@ -636,9 +640,27 @@ if (empty($reshook))
 	        if ($date_start_real_update == '') $date_start_real_update=$objectline->date_ouverture;
 	        if ($date_end_real_update == '')   $date_end_real_update=$objectline->date_cloture;
 	
-			$localtax1_tx=get_localtax(GETPOST('eltva_tx'),1,$object->thirdparty);
-	        $localtax2_tx=get_localtax(GETPOST('eltva_tx'),2,$object->thirdparty);
-	
+	        $vat_rate = GETPOST('eltva_tx');
+	        // Define info_bits
+	        $info_bits = 0;
+	        if (preg_match('/\*/', $vat_rate))
+	            $info_bits |= 0x01;
+	             
+    		// Define vat_rate
+    		$vat_rate = str_replace('*', '', $vat_rate);
+	        $localtax1_tx=get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
+	        $localtax2_tx=get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
+		
+	        $txtva = $vat_rate;
+	        
+		    // Clean vat code
+	        $vat_src_code='';
+	        if (preg_match('/\((.*)\)/', $txtva, $reg))
+	        {
+	            $vat_src_code = $reg[1];
+	            $txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
+	        }
+	        
 		  	// ajout prix d'achat
 		  	$fk_fournprice = $_POST['fournprice'];
 		  	if ( ! empty($_POST['buying_price']) )
@@ -653,7 +675,8 @@ if (empty($reshook))
 	        $objectline->subprice=GETPOST('elprice');
 	        $objectline->qty=GETPOST('elqty');
 	        $objectline->remise_percent=GETPOST('elremise_percent');
-	        $objectline->tva_tx=GETPOST('eltva_tx')?GETPOST('eltva_tx'):0;	// Field may be disabled, so we use vat rate 0
+	        $objectline->tva_tx=($txtva?$txtva:0);	// Field may be disabled, so we use vat rate 0
+	        $objectline->vat_src_code=$vat_src_code;
 	        $objectline->localtax1_tx=is_numeric($localtax1_tx)?$localtax1_tx:0;
 	        $objectline->localtax2_tx=is_numeric($localtax2_tx)?$localtax2_tx:0;
 	        $objectline->date_ouverture_prevue=$date_start_update;
@@ -1432,7 +1455,7 @@ else
         {
             print '<form name="update" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'" method="post">';
             print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
-            print '<input type="hidden" name="action" value="updateligne">';
+            print '<input type="hidden" name="action" value="updateline">';
             print '<input type="hidden" name="elrowid" value="'.$object->lines[$cursorline-1]->id.'">';
             print '<input type="hidden" name="idprod" value="'.(!empty($object->lines[$cursorline-1]->fk_product) ? $object->lines[$cursorline-1]->fk_product : 0).'">';
             print '<input type="hidden" name="fournprice" value="'.(!empty($object->lines[$cursorline-1]->fk_fournprice) ? $object->lines[$cursorline-1]->fk_fournprice : 0).'">';
@@ -1440,8 +1463,8 @@ else
             // Area with common detail of line
             print '<table class="notopnoleftnoright allwidth tableforservicepart1" width="100%">';
 
-            $sql = "SELECT cd.rowid, cd.statut, cd.label as label_det, cd.fk_product, cd.description, cd.price_ht, cd.qty,";
-            $sql.= " cd.tva_tx, cd.remise_percent, cd.info_bits, cd.subprice, cd.multicurrency_subprice,";
+            $sql = "SELECT cd.rowid, cd.statut, cd.label as label_det, cd.fk_product, cd.product_type, cd.description, cd.price_ht, cd.qty,";
+            $sql.= " cd.tva_tx, cd.vat_src_code, cd.remise_percent, cd.info_bits, cd.subprice, cd.multicurrency_subprice,";
             $sql.= " cd.date_ouverture_prevue as date_debut, cd.date_ouverture as date_debut_reelle,";
             $sql.= " cd.date_fin_validite as date_fin, cd.date_cloture as date_fin_reelle,";
             $sql.= " cd.commentaire as comment, cd.fk_product_fournisseur_price as fk_fournprice, cd.buy_price_ht as pa_ht,";
@@ -1510,7 +1533,9 @@ else
                         print '<td>'.dol_htmlentitiesbr($objp->description)."</td>\n";
                     }
                     // TVA
-                    print '<td align="center">'.vatrate($objp->tva_tx,'%',$objp->info_bits).'</td>';
+                    print '<td align="center">';
+                    print vatrate($objp->tva_tx.($objp->vat_src_code?(' ('.$objp->vat_src_code.')'):''), '%', $objp->info_bits);
+                    print '</td>';
                     // Price
                     print '<td align="right">'.($objp->subprice != '' ? price($objp->subprice) : '')."</td>\n";
                     // Price multicurrency
@@ -1643,7 +1668,7 @@ else
 
                     print '</td>';
                     print '<td align="right">';
-                    print $form->load_tva("eltva_tx",$objp->tva_tx,$mysoc,$object->thirdparty);
+                    print $form->load_tva("eltva_tx", $objp->tva_tx.($objp->vat_src_code?(' ('.$objp->vat_src_code.')'):''), $mysoc, $object->thirdparty, $objp->fk_product, $objp->info_bits, $objp->product_type, 0, 1);
                     print '</td>';
                     print '<td align="right"><input size="5" type="text" name="elprice" value="'.price($objp->subprice).'"></td>';
                     print '<td align="center"><input size="2" type="text" name="elqty" value="'.$objp->qty.'"></td>';
@@ -1938,7 +1963,7 @@ else
 			print "\n";
 			print '	<form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline')?'#add':'#line_'.GETPOST('lineid')).'" method="POST">
 			<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">
-			<input type="hidden" name="action" value="'.(($action != 'editline')?'addline':'updateligne').'">
+			<input type="hidden" name="action" value="'.(($action != 'editline')?'addline':'updateline').'">
 			<input type="hidden" name="mode" value="">
 			<input type="hidden" name="id" value="'.$object->id.'">
 			';

+ 12 - 2
htdocs/contrat/class/contrat.class.php

@@ -1357,7 +1357,14 @@ class Contrat extends CommonObject
 			// la part ht, tva et ttc, et ce au niveau de la ligne qui a son propre taux tva.
 
 			$localtaxes_type=getLocalTaxesFromRate($txtva, 0, $this->societe, $mysoc);
-			$txtva = preg_replace('/\s*\(.*\)/','',$txtva);  // Remove code into vatrate.
+
+		    // Clean vat code
+    		$vat_src_code='';
+    		if (preg_match('/\((.*)\)/', $txtva, $reg))
+    		{
+    		    $vat_src_code = $reg[1];
+    		    $txtva = preg_replace('/\s*\(.*\)/', '', $txtva);    // Remove code into vatrate.
+    		}
 
 			$tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, 1,$mysoc, $localtaxes_type);
 			$total_ht  = $tabprice[0];
@@ -1397,7 +1404,7 @@ class Contrat extends CommonObject
 
 			// Insertion dans la base
 			$sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet";
-			$sql.= " (fk_contrat, label, description, fk_product, qty, tva_tx,";
+			$sql.= " (fk_contrat, label, description, fk_product, qty, tva_tx, vat_src_code,";
 			$sql.= " localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice,";
 			$sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
 			$sql.= " info_bits,";
@@ -1410,6 +1417,7 @@ class Contrat extends CommonObject
 			$sql.= ($fk_product>0 ? $fk_product : "null").",";
 			$sql.= " ".$qty.",";
 			$sql.= " ".$txtva.",";
+			$sql.= " ".($vat_src_code?"'".$vat_src_code."'":"null").",";
 			$sql.= " ".$txlocaltax1.",";
 			$sql.= " ".$txlocaltax2.",";
 			$sql.= " '".$localtax1_type."',";
@@ -2598,6 +2606,7 @@ class ContratLigne extends CommonObjectLine
 		$sql.= " t.date_fin_validite as date_fin_validite,";
 		$sql.= " t.date_cloture as date_cloture,";
 		$sql.= " t.tva_tx,";
+		$sql.= " t.vat_src_code,";
 		$sql.= " t.localtax1_tx,";
 		$sql.= " t.localtax2_tx,";
 		$sql.= " t.qty,";
@@ -2650,6 +2659,7 @@ class ContratLigne extends CommonObjectLine
 				$this->date_fin_validite = $this->db->jdate($obj->date_fin_validite);
 				$this->date_cloture = $this->db->jdate($obj->date_cloture);
 				$this->tva_tx = $obj->tva_tx;
+				$this->vat_src_code = $obj->vat_src_code;
 				$this->localtax1_tx = $obj->localtax1_tx;
 				$this->localtax2_tx = $obj->localtax2_tx;
 				$this->qty = $obj->qty;

+ 8 - 7
htdocs/core/lib/functions.lib.php

@@ -379,7 +379,7 @@ function dol_include_once($relpath, $classname='')
 
 
 /**
- *	Return path of url or filesystem. Return alternate root if exists
+ *	Return path of url or filesystem. Return alternate root if exists.
  *
  * 	@param	string	$path		Relative path to file (if mode=0) or relative url (if mode=1). Ie: mydir/myfile, ../myfile
  *  @param	int		$type		0=Used for a Filesystem path, 1=Used for an URL path (output relative), 2=Used for an URL path (output full path using same host that current url), 3=Used for an URL path (output full path using host defined into $dolibarr_main_url_root of conf file)
@@ -3900,7 +3900,7 @@ function getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisi
     	$sql.= " AND t.taux = ".((float) $vatratecleaned)." AND t.active = 1";
     	if ($vatratecode) $sql.= " AND t.code ='".$vatratecode."'";
 	}
-	
+
 	$resql=$db->query($sql);
 	if ($resql)
 	{
@@ -3959,11 +3959,12 @@ function getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisi
 
 /**
  *	Return vat rate of a product in a particular selling country or default country vat if product is unknown
- *
+ *  Function called by get_default_tva
+ *  
  *  @param	int			$idprod          	Id of product or 0 if not a predefined product
  *  @param  Societe		$thirdparty_seller  Thirdparty with a ->country_code defined (FR, US, IT, ...)
  *	@param	int			$idprodfournprice	Id product_fournisseur_price (for "supplier" order/invoice)
- *  @return float					        Vat rate
+ *  @return float|string   				    Vat rate to use with format 5.0 or '5.0 (XXX)'
  *  @see get_product_localtax_for_country
  */
 function get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice=0)
@@ -3991,14 +3992,14 @@ function get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournpr
 			else
 			{
 				$ret=$product->tva_tx;    // Default vat of product we defined
-				// TODO Add ' ('.$product->default_vat_code.')';
+				if ($product->default_vat_code) $ret.=' ('.$product->default_vat_code.')';
 			}
 			$found=1;
 		}
 		else
 		{
 			// TODO Read default product vat according to countrycode and product. Vat for couple countrycode/product is a feature not implemeted yet. 
-			// Such feature is useless for 99.999% of users, probably 100%
+			// May be usefull/required if hidden option SERVICE_ARE_ECOMMERCE_200238EC is on
 		}
 	}
 
@@ -4113,7 +4114,7 @@ function get_product_localtax_for_country($idprod, $local, $thirdparty_seller)
  *	@param  Societe		$thirdparty_buyer   	Objet societe acheteuse
  *	@param  int			$idprod					Id product
  *	@param	int			$idprodfournprice		Id product_fournisseur_price (for supplier order/invoice)
- *	@return float         				      	Vat rate to use, -1 if we can't guess it
+ *	@return float|string   				      	Vat rate to use with format 5.0 or '5.0 (XXX)', -1 if we can't guess it
  *  @see get_default_npr, get_default_localtax
  */
 function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)

+ 1 - 1
htdocs/core/tpl/objectline_view.tpl.php

@@ -134,7 +134,7 @@ if (empty($usemargins)) $usemargins=0;
 	<?php } 
 	// VAT Rate
 	?>
-	<td align="right" class="linecolvat nowrap"><?php $coldisplay++; ?><?php echo vatrate($line->tva_tx.($line->vat_src_code?(' ('.$line->vat_src_code.')'):''),'%',$line->info_bits); ?></td>
+	<td align="right" class="linecolvat nowrap"><?php $coldisplay++; ?><?php echo vatrate($line->tva_tx.($line->vat_src_code?(' ('.$line->vat_src_code.')'):''), '%', $line->info_bits); ?></td>
 
 	<td align="right" class="linecoluht nowrap"><?php $coldisplay++; ?><?php echo price($line->subprice); ?></td>
 	

+ 1 - 0
htdocs/install/mysql/migration/4.0.0-5.0.0.sql

@@ -166,6 +166,7 @@ ALTER TABLE llx_commandedet ADD COLUMN vat_src_code varchar(10) DEFAULT '' AFTER
 ALTER TABLE llx_commande_fournisseurdet ADD COLUMN vat_src_code varchar(10) DEFAULT '' AFTER tva_tx;
 ALTER TABLE llx_propaldet ADD COLUMN vat_src_code varchar(10) DEFAULT '' AFTER tva_tx;
 ALTER TABLE llx_supplier_proposaldet ADD COLUMN vat_src_code varchar(10) DEFAULT '' AFTER tva_tx;
+ALTER TABLE llx_contratdet ADD COLUMN vat_src_code varchar(10) DEFAULT '' AFTER tva_tx;
 
 ALTER TABLE llx_c_payment_term change fdm type_cdr tinyint;
 

+ 9 - 8
htdocs/install/mysql/tables/llx_contratdet.sql

@@ -29,7 +29,7 @@ create table llx_contratdet
 
   label                 text,                              -- libelle du produit
   description           text,
-  fk_remise_except		  integer       NULL,                -- Lien vers table des remises fixes
+  fk_remise_except		integer       NULL,                -- Lien vers table des remises fixes
 
   date_commande         datetime,
   date_ouverture_prevue datetime,
@@ -37,15 +37,16 @@ create table llx_contratdet
   date_fin_validite     datetime,
   date_cloture          datetime,
 
-  tva_tx                double(6,3)   DEFAULT 0, 	         -- taux tva
-  localtax1_tx		double(6,3)   DEFAULT 0,           -- local tax 1 rate
-  localtax1_type			 	varchar(10)	  	 NULL, 			 -- localtax1 type
-  localtax2_tx		double(6,3)   DEFAULT 0,           -- local tax 2 rate
-  localtax2_type			 	varchar(10)	  	 NULL, 			 -- localtax2 type
+  vat_src_code			varchar(10)   DEFAULT '',		   -- Vat code used as source of vat fields. Not strict foreign key here.
+  tva_tx                double(6,3)   DEFAULT 0, 	       -- taux tva
+  localtax1_tx		    double(6,3)   DEFAULT 0,           -- local tax 1 rate
+  localtax1_type		varchar(10)	  	 NULL, 		       -- localtax1 type
+  localtax2_tx		    double(6,3)   DEFAULT 0,           -- local tax 2 rate
+  localtax2_type		varchar(10)	  	 NULL, 			   -- localtax2 type
   qty                   real          NOT NULL,            -- quantity
-  remise_percent        real          DEFAULT 0,    		   -- pourcentage de remise
+  remise_percent        real          DEFAULT 0,    	   -- pourcentage de remise
   subprice              double(24,8)  DEFAULT 0,           -- prix unitaire
-  price_ht              real,              		             -- prix final (obsolete)
+  price_ht              real,              		           -- prix final (obsolete)
   remise                real          DEFAULT 0,    		             -- montant de la remise (obsolete)
   total_ht              double(24,8)  DEFAULT 0,     		   -- Total HT de la ligne toute quantite et incluant remise ligne et globale
   total_tva             double(24,8)  DEFAULT 0,	   		   -- Total TVA de la ligne toute quantite et incluant remise ligne et globale

+ 7 - 6
htdocs/langs/en_US/admin.lang

@@ -916,7 +916,7 @@ Host=Server
 DriverType=Driver type
 SummarySystem=System information summary
 SummaryConst=List of all Dolibarr setup parameters
-MenuCompanySetup=Company/Foundation
+MenuCompanySetup=Company/Organisation
 DefaultMenuManager= Standard menu manager
 DefaultMenuSmartphoneManager=Smartphone menu manager
 Skin=Skin theme
@@ -930,8 +930,8 @@ PermanentLeftSearchForm=Permanent search form on left menu
 DefaultLanguage=Default language to use (language code)
 EnableMultilangInterface=Enable multilingual interface
 EnableShowLogo=Show logo on left menu
-CompanyInfo=Company/foundation information
-CompanyIds=Company/foundation identities
+CompanyInfo=Company/organisation information
+CompanyIds=Company/organisation identities
 CompanyName=Name
 CompanyAddress=Address
 CompanyZip=Zip
@@ -964,8 +964,8 @@ Delays_MAIN_DELAY_MEMBERS=Tolerance delay (in days) before alert on delayed memb
 Delays_MAIN_DELAY_CHEQUES_TO_DEPOSIT=Tolerance delay (in days) before alert for cheques deposit to do
 Delays_MAIN_DELAY_EXPENSEREPORTS=Tolerance delay (in days) before alert for expense reports to approve
 SetupDescription1=The setup area is for initial setup parameters before starting to use Dolibarr.
-SetupDescription2=The two most important setup steps are the first two in the setup menu on the left: Company/foundation setup page and Modules setup page:
-SetupDescription3=Parameters in menu <a href="%s">Setup -> Company/foundation</a> are required because submitted data are used on Dolibarr displays and to customize the default behaviour of the software (for country-related features for example).
+SetupDescription2=The two most important setup steps are the first two in the setup menu on the left: Company/Organisation setup page and Modules setup page:
+SetupDescription3=Parameters in menu <a href="%s">Setup -> Company/Organisation</a> are required because submitted data are used on Dolibarr displays and to customize the default behaviour of the software (for country-related features for example).
 SetupDescription4=Parameters in menu <a href="%s">Setup -> Modules</a> are required because Dolibarr is not a monolithic ERP/CRM but a collection of several modules, all more or less independent. New features will be added to menus for every module you'll enable.
 SetupDescription5=Other menu entries manage optional parameters.
 LogEvents=Security audit events
@@ -1463,7 +1463,7 @@ SupposedToBeInvoiceDate=Invoice date used
 Buy=Buy
 Sell=Sell
 InvoiceDateUsed=Invoice date used
-YourCompanyDoesNotUseVAT=Your company has been defined to not use VAT (Home - Setup - Company/Foundation), so there is no VAT options to setup.
+YourCompanyDoesNotUseVAT=Your company has been defined to not use VAT (Home - Setup - Company/Organisation), so there is no VAT options to setup.
 AccountancyCode=Accountancy Code
 AccountancyCodeSell=Sale account. code
 AccountancyCodeBuy=Purchase account. code 
@@ -1651,6 +1651,7 @@ SamePriceAlsoForSharedCompanies=If you use a multicompany module, with the choic
 ModuleEnabledAdminMustCheckRights=Module has been activated. Permissions for activated module(s) were given to admin users only. You may need to grant permissions to other users or groups manually if necessary.
 UserHasNoPermissions=This user has no permission defined
 TypeCdr=Use "None" if the date of payment term is date of invoice plus a delta in days (delta is field "Nb of days")<br>Use "At end of month", if, after delta, the date must be increased to reach the end of month (+ an optional "Offset" in days)<br>Use "Current/Next" to have payment term date being the first Nth of the month (N is stored into field "Nb of days")
+BaseCurrency=Reference currency of the company (go into setup of company to change this)
 ##### Resource ####
 ResourceSetup=Configuration du module Resource 
 UseSearchToSelectResource=Use a search form to choose a resource (rather than a drop-down list).

+ 0 - 1
htdocs/langs/en_US/companies.lang

@@ -38,7 +38,6 @@ ThirdPartyCustomersStats=Customers
 ThirdPartyCustomersWithIdProf12=Customers with %s or %s
 ThirdPartySuppliers=Suppliers
 ThirdPartyType=Third party type
-Company/Fundation=Company/Foundation
 Individual=Private individual
 ToCreateContactWithSameName=Will create automatically a contact/address with same information than third party under the third party. In most cases, even if your third party is a physical people, creating a third party alone is enough.
 ParentCompany=Parent company

+ 2 - 2
htdocs/langs/en_US/main.lang

@@ -43,7 +43,7 @@ ErrorConstantNotDefined=Parameter %s not defined
 ErrorUnknown=Unknown error
 ErrorSQL=SQL Error
 ErrorLogoFileNotFound=Logo file '%s' was not found
-ErrorGoToGlobalSetup=Go to 'Company/Foundation' setup to fix this
+ErrorGoToGlobalSetup=Go to 'Company/Organisation' setup to fix this
 ErrorGoToModuleSetup=Go to Module setup to fix this
 ErrorFailedToSendMail=Failed to send mail (sender=%s, receiver=%s)
 ErrorFileNotUploaded=File was not uploaded. Check that size does not exceed maximum allowed, that free space is available on disk and that there is not already a file with same name in this directory.
@@ -387,7 +387,7 @@ ActionRunningNotStarted=To start
 ActionRunningShort=In progress
 ActionDoneShort=Finished
 ActionUncomplete=Uncomplete
-CompanyFoundation=Company/Foundation
+CompanyFoundation=Company/Organisation
 ContactsForCompany=Contacts for this third party
 ContactsAddressesForCompany=Contacts/addresses for this third party
 AddressesForCompany=Addresses for this third party

+ 1 - 1
htdocs/langs/en_US/trips.lang

@@ -12,7 +12,7 @@ ListOfFees=List of fees
 TypeFees=Types of fees
 ShowTrip=Show expense report
 NewTrip=New expense report
-CompanyVisited=Company/foundation visited
+CompanyVisited=Company/organisation visited
 FeesKilometersOrAmout=Amount or kilometers
 DeleteTrip=Delete expense report
 ConfirmDeleteTrip=Are you sure you want to delete this expense report?

+ 2 - 2
htdocs/langs/en_US/users.lang

@@ -66,8 +66,8 @@ InternalUser=Internal user
 ExportDataset_user_1=Dolibarr's users and properties
 DomainUser=Domain user %s
 Reactivate=Reactivate
-CreateInternalUserDesc=This form allows you to create an user internal to your company/foundation. To create an external user (customer, supplier, ...), use the button 'Create Dolibarr user' from third party's contact card.
-InternalExternalDesc=An <b>internal</b> user is a user that is part of your company/foundation.<br>An <b>external</b> user is a customer, supplier or other.<br><br>In both cases, permissions defines rights on Dolibarr, also external user can have a different menu manager than internal user (See Home - Setup - Display)
+CreateInternalUserDesc=This form allows you to create an user internal to your company/organisation. To create an external user (customer, supplier, ...), use the button 'Create Dolibarr user' from third party's contact card.
+InternalExternalDesc=An <b>internal</b> user is a user that is part of your company/organisation.<br>An <b>external</b> user is a customer, supplier or other.<br><br>In both cases, permissions defines rights on Dolibarr, also external user can have a different menu manager than internal user (See Home - Setup - Display)
 PermissionInheritedFromAGroup=Permission granted because inherited from one of a user's group.
 Inherited=Inherited
 UserWillBeInternalUser=Created user will be an internal user (because not linked to a particular third party)

+ 6 - 3
htdocs/product/card.php

@@ -641,13 +641,16 @@ if (empty($reshook))
                 }
             }
 
+			$tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
+			$tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
+            
             // On reevalue prix selon taux tva car taux tva transaction peut etre different
             // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
-            if ($tva_tx != $object->tva_tx) {
+            if ($tmpvat != $tmpprodvat) {
                 if ($price_base_type != 'HT') {
-                    $pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU');
+                    $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
                 } else {
-                    $pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
+                    $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
                 }
             }
             

+ 7 - 6
htdocs/product/class/product.class.php

@@ -1773,14 +1773,14 @@ class Product extends CommonObject
 
 				// multilangs
 				if (! empty($conf->global->MAIN_MULTILANGS)) $this->getMultiLangs();
-
+				
 				// Load multiprices array
 				if (! empty($conf->global->PRODUIT_MULTIPRICES))
 				{
 					for ($i=1; $i <= $conf->global->PRODUIT_MULTIPRICES_LIMIT; $i++)
 					{
 						$sql = "SELECT price, price_ttc, price_min, price_min_ttc,";
-						$sql.= " price_base_type, tva_tx, tosell, price_by_qty, rowid, recuperableonly";
+						$sql.= " price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid, recuperableonly";
 						$sql.= " FROM ".MAIN_DB_PREFIX."product_price";
 						$sql.= " WHERE entity IN (".getEntity('productprice', 1).")";
 						$sql.= " AND price_level=".$i;
@@ -1797,7 +1797,8 @@ class Product extends CommonObject
 							$this->multiprices_min[$i]=$result["price_min"];
 							$this->multiprices_min_ttc[$i]=$result["price_min_ttc"];
 							$this->multiprices_base_type[$i]=$result["price_base_type"];
-							$this->multiprices_tva_tx[$i]=$result["tva_tx"];
+							// Next two fields are used only if PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL is on
+							$this->multiprices_tva_tx[$i]=$result["tva_tx"];     // TODO Add ' ('.$result['default_vat_code'].')'
 							$this->multiprices_recuperableonly[$i]=$result["recuperableonly"];
 
 							// Price by quantity
@@ -1806,7 +1807,7 @@ class Product extends CommonObject
 							// Récuperation de la liste des prix selon qty si flag positionné
 							if ($this->prices_by_qty[$i] == 1)
 							{
-								$sql = "SELECT rowid,price, unitprice, quantity, remise_percent, remise";
+								$sql = "SELECT rowid, price, unitprice, quantity, remise_percent, remise";
 								$sql.= " FROM ".MAIN_DB_PREFIX."product_price_by_qty";
 								$sql.= " WHERE fk_product_price = '".$this->prices_by_qty_id[$i]."'";
 								$sql.= " ORDER BY quantity ASC";
@@ -1843,7 +1844,7 @@ class Product extends CommonObject
 				} else if (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
 				{
 					$sql = "SELECT price, price_ttc, price_min, price_min_ttc,";
-					$sql.= " price_base_type, tva_tx, tosell, price_by_qty, rowid";
+					$sql.= " price_base_type, tva_tx, default_vat_code, tosell, price_by_qty, rowid";
 					$sql.= " FROM ".MAIN_DB_PREFIX."product_price";
 					$sql.= " WHERE fk_product = '".$this->id."'";
 					$sql.= " ORDER BY date_price DESC, rowid DESC";
@@ -1902,7 +1903,7 @@ class Product extends CommonObject
                     if ($price_result >= 0)
                     {
                         $this->price = $price_result;
-                        //Calculate the VAT
+                        // Calculate the VAT
 						$this->price_ttc = price2num($this->price) * (1 + ($this->tva_tx / 100));
 						$this->price_ttc = price2num($this->price_ttc,'MU');
                     }

+ 1 - 1
htdocs/societe/canvas/company/tpl/card_create.tpl.php

@@ -29,7 +29,7 @@
 <br>
 <?php echo $langs->trans("ThirdPartyType") ?>: &nbsp;
 <input type="radio" id="radiocompany" class="flat" name="private" value="0" checked>
-<?php echo $langs->trans("Company/Fundation"); ?> &nbsp; &nbsp;
+<?php echo $langs->trans("CompanyFoundation"); ?> &nbsp; &nbsp;
 <input type="radio" id="radioprivate" class="flat" name="private" value="1"> <?php echo $langs->trans("Individual"); ?> (<?php echo $langs->trans("ToCreateContactWithSameName") ?>)
 <br>
 <br>

+ 1 - 1
htdocs/societe/canvas/individual/tpl/card_create.tpl.php

@@ -29,7 +29,7 @@
 <br>
 <?php echo $langs->trans("ThirdPartyType") ?>: &nbsp;
 <input type="radio" id="radiocompany" class="flat" name="private" value="0">
-<?php echo $langs->trans("Company/Fundation"); ?> &nbsp; &nbsp;
+<?php echo $langs->trans("CompanyFoundation"); ?> &nbsp; &nbsp;
 <input type="radio" id="radioprivate" class="flat" name="private" value="1" checked> <?php echo $langs->trans("Individual"); ?> (<?php echo $langs->trans("ToCreateContactWithSameName") ?>)
 <br>
 <br>