FIX The vat rate line used when adding a predefined product was wrong if

there is several vat line with same rate.
This commit is contained in:
Laurent Destailleur
2017-03-04 21:45:19 +01:00
parent 74ba7b4b51
commit f67c967d0b
20 changed files with 303 additions and 251 deletions

View File

@@ -731,9 +731,11 @@ if (empty($reshook))
$db->begin(); $db->begin();
// $tva_tx can be 'x.x (XXX)'
// Ecrase $pu par celui du produit // Ecrase $pu par celui du produit
// Ecrase $desc 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 // Replaces $fk_unit with the product unit
if (! empty($idprod)) { if (! empty($idprod)) {
$prod = new Product($db); $prod = new Product($db);
@@ -741,12 +743,10 @@ if (empty($reshook))
$label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : ''); $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_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
$tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id); $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
if (empty($tva_tx)) $tva_npr=0; if (empty($tva_tx)) $tva_npr=0;
var_dump($tva_tx);
exit;
$pu_ht = $prod->price; $pu_ht = $prod->price;
$pu_ttc = $prod->price_ttc; $pu_ttc = $prod->price_ttc;
@@ -756,7 +756,7 @@ exit;
// On defini prix unitaire // On defini prix unitaire
if (! empty($conf->global->PRODUIT_MULTIPRICES) && $object->thirdparty->price_level) 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]; $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
$price_min = $prod->multiprices_min[$object->thirdparty->price_level]; $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
$price_base_type = $prod->multiprices_base_type[$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); $result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
if ($result) { if ($result) {
if (count($prodcustprice->lines) > 0) { if (count($prodcustprice->lines) > 0) {
$pu_ht = price($prodcustprice->lines [0]->price); $pu_ht = price($prodcustprice->lines[0]->price);
$pu_ttc = price($prodcustprice->lines [0]->price_ttc); $pu_ttc = price($prodcustprice->lines[0]->price_ttc);
$price_base_type = $prodcustprice->lines [0]->price_base_type; $price_base_type = $prodcustprice->lines[0]->price_base_type;
$tva_tx = $prodcustprice->lines [0]->tva_tx; $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)) { if (! empty($price_ht)) {
$pu_ht = price2num($price_ht, 'MU'); $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 // 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). // 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') { 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 { } else {
$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU'); $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
} }
} }

View File

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

View File

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

View File

@@ -1394,7 +1394,7 @@ if (empty($reshook))
// Ecrase $pu par celui du produit // Ecrase $pu par celui du produit
// Ecrase $desc 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 // Ecrase $base_price_type par celui du produit
// Replaces $fk_unit with the product's // Replaces $fk_unit with the product's
if (! empty($idprod)) if (! empty($idprod))
@@ -1405,102 +1405,105 @@ if (empty($reshook))
$label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : ''); $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
// Update if prices fields are defined // Update if prices fields are defined
$tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id); $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
$tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id); $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
if (empty($tva_tx)) $tva_npr=0; if (empty($tva_tx)) $tva_npr=0;
$pu_ht = $prod->price; $pu_ht = $prod->price;
$pu_ttc = $prod->price_ttc; $pu_ttc = $prod->price_ttc;
$price_min = $prod->price_min; $price_min = $prod->price_min;
$price_base_type = $prod->price_base_type; $price_base_type = $prod->price_base_type;
// We define price for product // We define price for product
if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level)) 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]; if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) $tva_tx=$prod->multiprices_tva_tx[$object->thirdparty->price_level];
$pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level]; if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) $tva_npr=$prod->multiprices_recuperableonly[$object->thirdparty->price_level];
$price_min = $prod->multiprices_min[$object->thirdparty->price_level]; if (empty($tva_tx)) $tva_npr=0;
$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 }
{ elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES))
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]; require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
if (empty($tva_tx)) $tva_npr=0;
$prodcustprice = new Productcustomerprice($db);
$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;
} }
} }
elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES)) }
$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')
{ {
require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php'; $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
$prodcustprice = new Productcustomerprice($db);
$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;
}
}
} }
else
// if price ht was forced (ie: from gui when calculated by margin rate and cost price)
if (! empty($price_ht))
{ {
$pu_ht = price2num($price_ht, 'MU'); $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 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) $desc = '';
{
if ($price_base_type != 'HT') // Define output language
{ if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
$pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU'); $outputlangs = $langs;
} $newlang = '';
else if (empty($newlang) && GETPOST('lang_id'))
{ $newlang = GETPOST('lang_id');
$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU'); if (empty($newlang))
} $newlang = $object->thirdparty->default_lang;
if (! empty($newlang)) {
$outputlangs = new Translate("", $conf);
$outputlangs->setDefaultLang($newlang);
} }
$desc = ''; $desc = (! empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
} else {
$desc = $prod->description;
}
// Define output language $desc = dol_concatdesc($desc, $product_desc);
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; // Add custom code and origin country into description
} else { if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) {
$desc = $prod->description; $tmptxt = '(';
} if (! empty($prod->customcode))
$tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
$desc = dol_concatdesc($desc, $product_desc); if (! empty($prod->customcode) && ! empty($prod->country_code))
$tmptxt .= ' - ';
// Add custom code and origin country into description if (! empty($prod->country_code))
if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) { $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
$tmptxt = '('; $tmptxt .= ')';
if (! empty($prod->customcode)) $desc = dol_concatdesc($desc, $tmptxt);
$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; $type = $prod->type;
$fk_unit = $prod->fk_unit; $fk_unit = $prod->fk_unit;

View File

@@ -456,7 +456,7 @@ if (empty($reshook))
// Ecrase $pu par celui du produit // Ecrase $pu par celui du produit
// Ecrase $desc 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 // Ecrase $base_price_type par celui du produit
// Replaces $fk_unit with the product's // Replaces $fk_unit with the product's
if (! empty($idprod)) 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)) if (! empty($price_ht))
{ {
$pu_ht = price2num($price_ht, 'MU'); $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 // 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). // 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') 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 else
{ {
$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU'); $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
} }
} }

View File

@@ -407,21 +407,21 @@ if (empty($reshook))
// Set if we used free entry or predefined product // Set if we used free entry or predefined product
$predef=''; $predef='';
$product_desc=(GETPOST('dp_desc')?GETPOST('dp_desc'):''); $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') if (GETPOST('prod_entry_mode') == 'free')
{ {
$idprod=0; $idprod=0;
$price_ht = GETPOST('price_ht');
$tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0); $tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
} }
else else
{ {
$idprod=GETPOST('idprod', 'int'); $idprod=GETPOST('idprod', 'int');
$price_ht = '';
$tva_tx = ''; $tva_tx = '';
} }
$qty = GETPOST('qty'.$predef); $qty = GETPOST('qty'.$predef);
$remise_percent=GETPOST('remise_percent'.$predef); $remise_percent = GETPOST('remise_percent'.$predef);
if ($qty == '') if ($qty == '')
{ {
@@ -455,13 +455,14 @@ if (empty($reshook))
// Ecrase $pu par celui du produit // Ecrase $pu par celui du produit
// Ecrase $desc 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 // Ecrase $base_price_type par celui du produit
if ($idprod > 0) if ($idprod > 0)
{ {
$prod = new Product($db); $prod = new Product($db);
$prod->fetch($idprod); $prod->fetch($idprod);
// Update if prices fields are defined
$tva_tx = get_default_tva($mysoc,$object->thirdparty,$prod->id); $tva_tx = get_default_tva($mysoc,$object->thirdparty,$prod->id);
$tva_npr = get_default_npr($mysoc,$object->thirdparty,$prod->id); $tva_npr = get_default_npr($mysoc,$object->thirdparty,$prod->id);
if (empty($tva_tx)) $tva_npr=0; 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). // 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') 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 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); $objectline = new ContratLigne($db);
if ($objectline->fetch(GETPOST('elrowid'))) 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_start_real_update == '') $date_start_real_update=$objectline->date_ouverture;
if ($date_end_real_update == '') $date_end_real_update=$objectline->date_cloture; if ($date_end_real_update == '') $date_end_real_update=$objectline->date_cloture;
$localtax1_tx=get_localtax(GETPOST('eltva_tx'),1,$object->thirdparty); $vat_rate = GETPOST('eltva_tx');
$localtax2_tx=get_localtax(GETPOST('eltva_tx'),2,$object->thirdparty); // 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 // ajout prix d'achat
$fk_fournprice = $_POST['fournprice']; $fk_fournprice = $_POST['fournprice'];
if ( ! empty($_POST['buying_price']) ) if ( ! empty($_POST['buying_price']) )
@@ -653,7 +675,8 @@ if (empty($reshook))
$objectline->subprice=GETPOST('elprice'); $objectline->subprice=GETPOST('elprice');
$objectline->qty=GETPOST('elqty'); $objectline->qty=GETPOST('elqty');
$objectline->remise_percent=GETPOST('elremise_percent'); $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->localtax1_tx=is_numeric($localtax1_tx)?$localtax1_tx:0;
$objectline->localtax2_tx=is_numeric($localtax2_tx)?$localtax2_tx:0; $objectline->localtax2_tx=is_numeric($localtax2_tx)?$localtax2_tx:0;
$objectline->date_ouverture_prevue=$date_start_update; $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 '<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="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="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="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).'">'; 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 // Area with common detail of line
print '<table class="notopnoleftnoright allwidth tableforservicepart1" width="100%">'; 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 = "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.remise_percent, cd.info_bits, cd.subprice, cd.multicurrency_subprice,"; $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_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.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,"; $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"; print '<td>'.dol_htmlentitiesbr($objp->description)."</td>\n";
} }
// TVA // 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 // Price
print '<td align="right">'.($objp->subprice != '' ? price($objp->subprice) : '')."</td>\n"; print '<td align="right">'.($objp->subprice != '' ? price($objp->subprice) : '')."</td>\n";
// Price multicurrency // Price multicurrency
@@ -1643,7 +1668,7 @@ else
print '</td>'; print '</td>';
print '<td align="right">'; 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>';
print '<td align="right"><input size="5" type="text" name="elprice" value="'.price($objp->subprice).'"></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>'; print '<td align="center"><input size="2" type="text" name="elqty" value="'.$objp->qty.'"></td>';
@@ -1938,7 +1963,7 @@ else
print "\n"; print "\n";
print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline')?'#add':'#line_'.GETPOST('lineid')).'" method="POST"> 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="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="mode" value="">
<input type="hidden" name="id" value="'.$object->id.'"> <input type="hidden" name="id" value="'.$object->id.'">
'; ';

View File

@@ -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. // 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); $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); $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]; $total_ht = $tabprice[0];
@@ -1397,7 +1404,7 @@ class Contrat extends CommonObject
// Insertion dans la base // Insertion dans la base
$sql = "INSERT INTO ".MAIN_DB_PREFIX."contratdet"; $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.= " localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, remise_percent, subprice,";
$sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,"; $sql.= " total_ht, total_tva, total_localtax1, total_localtax2, total_ttc,";
$sql.= " info_bits,"; $sql.= " info_bits,";
@@ -1410,6 +1417,7 @@ class Contrat extends CommonObject
$sql.= ($fk_product>0 ? $fk_product : "null").","; $sql.= ($fk_product>0 ? $fk_product : "null").",";
$sql.= " ".$qty.","; $sql.= " ".$qty.",";
$sql.= " ".$txtva.","; $sql.= " ".$txtva.",";
$sql.= " ".($vat_src_code?"'".$vat_src_code."'":"null").",";
$sql.= " ".$txlocaltax1.","; $sql.= " ".$txlocaltax1.",";
$sql.= " ".$txlocaltax2.","; $sql.= " ".$txlocaltax2.",";
$sql.= " '".$localtax1_type."',"; $sql.= " '".$localtax1_type."',";
@@ -2598,6 +2606,7 @@ class ContratLigne extends CommonObjectLine
$sql.= " t.date_fin_validite as date_fin_validite,"; $sql.= " t.date_fin_validite as date_fin_validite,";
$sql.= " t.date_cloture as date_cloture,"; $sql.= " t.date_cloture as date_cloture,";
$sql.= " t.tva_tx,"; $sql.= " t.tva_tx,";
$sql.= " t.vat_src_code,";
$sql.= " t.localtax1_tx,"; $sql.= " t.localtax1_tx,";
$sql.= " t.localtax2_tx,"; $sql.= " t.localtax2_tx,";
$sql.= " t.qty,"; $sql.= " t.qty,";
@@ -2650,6 +2659,7 @@ class ContratLigne extends CommonObjectLine
$this->date_fin_validite = $this->db->jdate($obj->date_fin_validite); $this->date_fin_validite = $this->db->jdate($obj->date_fin_validite);
$this->date_cloture = $this->db->jdate($obj->date_cloture); $this->date_cloture = $this->db->jdate($obj->date_cloture);
$this->tva_tx = $obj->tva_tx; $this->tva_tx = $obj->tva_tx;
$this->vat_src_code = $obj->vat_src_code;
$this->localtax1_tx = $obj->localtax1_tx; $this->localtax1_tx = $obj->localtax1_tx;
$this->localtax2_tx = $obj->localtax2_tx; $this->localtax2_tx = $obj->localtax2_tx;
$this->qty = $obj->qty; $this->qty = $obj->qty;

View File

@@ -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 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) * @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"; $sql.= " AND t.taux = ".((float) $vatratecleaned)." AND t.active = 1";
if ($vatratecode) $sql.= " AND t.code ='".$vatratecode."'"; if ($vatratecode) $sql.= " AND t.code ='".$vatratecode."'";
} }
$resql=$db->query($sql); $resql=$db->query($sql);
if ($resql) 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 * 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 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 Societe $thirdparty_seller Thirdparty with a ->country_code defined (FR, US, IT, ...)
* @param int $idprodfournprice Id product_fournisseur_price (for "supplier" order/invoice) * @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 * @see get_product_localtax_for_country
*/ */
function get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice=0) 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 else
{ {
$ret=$product->tva_tx; // Default vat of product we defined $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; $found=1;
} }
else else
{ {
// TODO Read default product vat according to countrycode and product. Vat for couple countrycode/product is a feature not implemeted yet. // 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 Societe $thirdparty_buyer Objet societe acheteuse
* @param int $idprod Id product * @param int $idprod Id product
* @param int $idprodfournprice Id product_fournisseur_price (for supplier order/invoice) * @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 * @see get_default_npr, get_default_localtax
*/ */
function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0) function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)

View File

@@ -134,7 +134,7 @@ if (empty($usemargins)) $usemargins=0;
<?php } <?php }
// VAT Rate // 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> <td align="right" class="linecoluht nowrap"><?php $coldisplay++; ?><?php echo price($line->subprice); ?></td>

View File

@@ -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_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_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_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; ALTER TABLE llx_c_payment_term change fdm type_cdr tinyint;

View File

@@ -29,7 +29,7 @@ create table llx_contratdet
label text, -- libelle du produit label text, -- libelle du produit
description text, 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_commande datetime,
date_ouverture_prevue datetime, date_ouverture_prevue datetime,
@@ -37,15 +37,16 @@ create table llx_contratdet
date_fin_validite datetime, date_fin_validite datetime,
date_cloture datetime, date_cloture datetime,
tva_tx double(6,3) DEFAULT 0, -- taux tva vat_src_code varchar(10) DEFAULT '', -- Vat code used as source of vat fields. Not strict foreign key here.
localtax1_tx double(6,3) DEFAULT 0, -- local tax 1 rate tva_tx double(6,3) DEFAULT 0, -- taux tva
localtax1_type varchar(10) NULL, -- localtax1 type localtax1_tx double(6,3) DEFAULT 0, -- local tax 1 rate
localtax2_tx double(6,3) DEFAULT 0, -- local tax 2 rate localtax1_type varchar(10) NULL, -- localtax1 type
localtax2_type varchar(10) NULL, -- localtax2 type localtax2_tx double(6,3) DEFAULT 0, -- local tax 2 rate
localtax2_type varchar(10) NULL, -- localtax2 type
qty real NOT NULL, -- quantity 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 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) 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_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 total_tva double(24,8) DEFAULT 0, -- Total TVA de la ligne toute quantite et incluant remise ligne et globale

View File

@@ -916,7 +916,7 @@ Host=Server
DriverType=Driver type DriverType=Driver type
SummarySystem=System information summary SummarySystem=System information summary
SummaryConst=List of all Dolibarr setup parameters SummaryConst=List of all Dolibarr setup parameters
MenuCompanySetup=Company/Foundation MenuCompanySetup=Company/Organisation
DefaultMenuManager= Standard menu manager DefaultMenuManager= Standard menu manager
DefaultMenuSmartphoneManager=Smartphone menu manager DefaultMenuSmartphoneManager=Smartphone menu manager
Skin=Skin theme Skin=Skin theme
@@ -930,8 +930,8 @@ PermanentLeftSearchForm=Permanent search form on left menu
DefaultLanguage=Default language to use (language code) DefaultLanguage=Default language to use (language code)
EnableMultilangInterface=Enable multilingual interface EnableMultilangInterface=Enable multilingual interface
EnableShowLogo=Show logo on left menu EnableShowLogo=Show logo on left menu
CompanyInfo=Company/foundation information CompanyInfo=Company/organisation information
CompanyIds=Company/foundation identities CompanyIds=Company/organisation identities
CompanyName=Name CompanyName=Name
CompanyAddress=Address CompanyAddress=Address
CompanyZip=Zip 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_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 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. 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: 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/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). 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. 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. SetupDescription5=Other menu entries manage optional parameters.
LogEvents=Security audit events LogEvents=Security audit events
@@ -1463,7 +1463,7 @@ SupposedToBeInvoiceDate=Invoice date used
Buy=Buy Buy=Buy
Sell=Sell Sell=Sell
InvoiceDateUsed=Invoice date used 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 AccountancyCode=Accountancy Code
AccountancyCodeSell=Sale account. code AccountancyCodeSell=Sale account. code
AccountancyCodeBuy=Purchase 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. 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 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") 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 #### ##### Resource ####
ResourceSetup=Configuration du module Resource ResourceSetup=Configuration du module Resource
UseSearchToSelectResource=Use a search form to choose a resource (rather than a drop-down list). UseSearchToSelectResource=Use a search form to choose a resource (rather than a drop-down list).

View File

@@ -38,7 +38,6 @@ ThirdPartyCustomersStats=Customers
ThirdPartyCustomersWithIdProf12=Customers with %s or %s ThirdPartyCustomersWithIdProf12=Customers with %s or %s
ThirdPartySuppliers=Suppliers ThirdPartySuppliers=Suppliers
ThirdPartyType=Third party type ThirdPartyType=Third party type
Company/Fundation=Company/Foundation
Individual=Private individual 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. 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 ParentCompany=Parent company

View File

@@ -43,7 +43,7 @@ ErrorConstantNotDefined=Parameter %s not defined
ErrorUnknown=Unknown error ErrorUnknown=Unknown error
ErrorSQL=SQL Error ErrorSQL=SQL Error
ErrorLogoFileNotFound=Logo file '%s' was not found 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 ErrorGoToModuleSetup=Go to Module setup to fix this
ErrorFailedToSendMail=Failed to send mail (sender=%s, receiver=%s) 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. 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 ActionRunningShort=In progress
ActionDoneShort=Finished ActionDoneShort=Finished
ActionUncomplete=Uncomplete ActionUncomplete=Uncomplete
CompanyFoundation=Company/Foundation CompanyFoundation=Company/Organisation
ContactsForCompany=Contacts for this third party ContactsForCompany=Contacts for this third party
ContactsAddressesForCompany=Contacts/addresses for this third party ContactsAddressesForCompany=Contacts/addresses for this third party
AddressesForCompany=Addresses for this third party AddressesForCompany=Addresses for this third party

View File

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

View File

@@ -66,8 +66,8 @@ InternalUser=Internal user
ExportDataset_user_1=Dolibarr's users and properties ExportDataset_user_1=Dolibarr's users and properties
DomainUser=Domain user %s DomainUser=Domain user %s
Reactivate=Reactivate 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. 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/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) 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. PermissionInheritedFromAGroup=Permission granted because inherited from one of a user's group.
Inherited=Inherited Inherited=Inherited
UserWillBeInternalUser=Created user will be an internal user (because not linked to a particular third party) UserWillBeInternalUser=Created user will be an internal user (because not linked to a particular third party)

View File

@@ -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 // 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). // 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') { 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 { } else {
$pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU'); $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
} }
} }

View File

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

View File

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

View File

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