';
} elseif ($value == 'localtax1_type' || $value == 'localtax2_type') {
// Le type de taxe locale
print '
';
diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php
index 1eb1a8721c6..d8653ba4220 100644
--- a/htdocs/core/class/html.form.class.php
+++ b/htdocs/core/class/html.form.class.php
@@ -6372,10 +6372,10 @@ class Form
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
/**
- * Load into the cache vat rates of a country
+ * Load into the cache ->cache_vatrates, all the vat rates of a country
*
- * @param string $country_code Country code with quotes ("'CA'", or "'CA,IN,...'")
- * @return int Nb of loaded lines, 0 if already loaded, <0 if KO
+ * @param string $country_code Country code with quotes ("'CA'", or "'CA,IN,...'")
+ * @return int Nb of loaded lines, 0 if already loaded, <0 if KO
*/
public function load_cache_vatrates($country_code)
{
@@ -6389,8 +6389,8 @@ class Form
dol_syslog(__METHOD__, LOG_DEBUG);
- $sql = "SELECT DISTINCT t.rowid, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
- $sql .= " FROM " . $this->db->prefix() . "c_tva as t, " . $this->db->prefix() . "c_country as c";
+ $sql = "SELECT t.rowid, t.type_vat, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly";
+ $sql .= " FROM ".$this->db->prefix()."c_tva as t, ".$this->db->prefix()."c_country as c";
$sql .= " WHERE t.fk_pays = c.rowid";
$sql .= " AND t.active > 0";
$sql .= " AND t.entity IN (".getEntity('c_tva').")";
@@ -6403,17 +6403,19 @@ class Form
if ($num) {
for ($i = 0; $i < $num; $i++) {
$obj = $this->db->fetch_object($resql);
- $this->cache_vatrates[$i]['rowid'] = $obj->rowid;
- $this->cache_vatrates[$i]['code'] = $obj->code;
- $this->cache_vatrates[$i]['txtva'] = $obj->taux;
- $this->cache_vatrates[$i]['nprtva'] = $obj->recuperableonly;
- $this->cache_vatrates[$i]['localtax1'] = $obj->localtax1;
- $this->cache_vatrates[$i]['localtax1_type'] = $obj->localtax1_type;
- $this->cache_vatrates[$i]['localtax2'] = $obj->localtax2;
- $this->cache_vatrates[$i]['localtax2_type'] = $obj->localtax1_type;
- $this->cache_vatrates[$i]['label'] = $obj->taux . '%' . ($obj->code ? ' (' . $obj->code . ')' : ''); // Label must contains only 0-9 , . % or *
- $this->cache_vatrates[$i]['labelallrates'] = $obj->taux . '/' . ($obj->localtax1 ? $obj->localtax1 : '0') . '/' . ($obj->localtax2 ? $obj->localtax2 : '0') . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
+ $tmparray = array();
+ $tmparray['rowid'] = $obj->rowid;
+ $tmparray['type_vat'] = $obj->type_vat;
+ $tmparray['code'] = $obj->code;
+ $tmparray['txtva'] = $obj->taux;
+ $tmparray['nprtva'] = $obj->recuperableonly;
+ $tmparray['localtax1'] = $obj->localtax1;
+ $tmparray['localtax1_type'] = $obj->localtax1_type;
+ $tmparray['localtax2'] = $obj->localtax2;
+ $tmparray['localtax2_type'] = $obj->localtax1_type;
+ $tmparray['label'] = $obj->taux . '%' . ($obj->code ? ' (' . $obj->code . ')' : ''); // Label must contains only 0-9 , . % or *
+ $tmparray['labelallrates'] = $obj->taux . '/' . ($obj->localtax1 ? $obj->localtax1 : '0') . '/' . ($obj->localtax2 ? $obj->localtax2 : '0') . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
$positiverates = '';
if ($obj->taux) {
$positiverates .= ($positiverates ? '/' : '') . $obj->taux;
@@ -6427,7 +6429,9 @@ class Form
if (empty($positiverates)) {
$positiverates = '0';
}
- $this->cache_vatrates[$i]['labelpositiverates'] = $positiverates . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
+ $tmparray['labelpositiverates'] = $positiverates . ($obj->code ? ' (' . $obj->code . ')' : ''); // Must never be used as key, only label
+
+ $this->cache_vatrates[$obj->rowid] = $tmparray;
}
return $num;
@@ -6456,24 +6460,25 @@ class Form
* Output an HTML select vat rate.
* The name of this function should be selectVat. We keep bad name for compatibility purpose.
*
- * @param string $htmlname Name of HTML select field
- * @param float|string $selectedrate Force preselected vat rate. Can be '8.5' or '8.5 (NOO)' for example. Use '' for no forcing.
- * @param Societe $societe_vendeuse Thirdparty seller
- * @param Societe $societe_acheteuse Thirdparty buyer
- * @param int $idprod Id product. O if unknown of NA.
- * @param int $info_bits Miscellaneous information on line (1 for NPR)
- * @param int|string $type ''=Unknown, 0=Product, 1=Service (Used if idprod not defined)
- * If seller not subject to VAT, default VAT=0. End of rule.
- * If (seller country==buyer country), then default VAT=product's VAT. End of rule.
- * If (seller and buyer in EU) and sold product = new means of transportation (car, boat, airplane), default VAT =0 (VAT must be paid by the buyer to his country's tax office and not the seller). End of rule.
- * If (seller and buyer in EU) and buyer=private person, then default VAT=VAT of sold product. End of rule.
- * If (seller and buyer in EU) and buyer=company then default VAT =0. End of rule.
- * Else, default proposed VAT==0. End of rule.
- * @param bool $options_only Return HTML options lines only (for ajax treatment)
- * @param int $mode 0=Use vat rate as key in combo list, 1=Add VAT code after vat rate into key, -1=Use id of vat line as key
- * @return string
+ * @param string $htmlname Name of HTML select field
+ * @param float|string $selectedrate Force preselected vat rate. Can be '8.5' or '8.5 (NOO)' for example. Use '' for no forcing.
+ * @param Societe $societe_vendeuse Thirdparty seller
+ * @param Societe $societe_acheteuse Thirdparty buyer
+ * @param int $idprod Id product. O if unknown of NA.
+ * @param int $info_bits Miscellaneous information on line (1 for NPR)
+ * @param int|string $type ''=Unknown, 0=Product, 1=Service (Used if idprod not defined)
+ * If seller not subject to VAT, default VAT=0. End of rule.
+ * If (seller country==buyer country), then default VAT=product's VAT. End of rule.
+ * If (seller and buyer in EU) and sold product = new means of transportation (car, boat, airplane), default VAT =0 (VAT must be paid by the buyer to his country's tax office and not the seller). End of rule.
+ * If (seller and buyer in EU) and buyer=private person, then default VAT=VAT of sold product. End of rule.
+ * If (seller and buyer in EU) and buyer=company then default VAT =0. End of rule.
+ * Else, default proposed VAT==0. End of rule.
+ * @param bool $options_only Return HTML options lines only (for ajax treatment)
+ * @param int $mode 0=Use vat rate as key in combo list, 1=Add VAT code after vat rate into key, -1=Use id of vat line as key
+ * @param int $type_vat 0=All type, 1=VAT rate sale, 2=VAT rate purchase
+ * @return string
*/
- public function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = null, $societe_acheteuse = null, $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0)
+ public function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = null, $societe_acheteuse = null, $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0, $type_vat = 0)
{
// phpcs:enable
global $langs, $conf, $mysoc;
@@ -6535,8 +6540,17 @@ class Form
}
}
- // Now we get list
- $num = $this->load_cache_vatrates($code_country); // If no vat defined, return -1 with message into this->error
+ // Now we load the list of VAT
+ $this->load_cache_vatrates($code_country); // If no vat defined, return -1 with message into this->error
+ // Keep only the VAT qualified for $type_vat
+ $arrayofvatrates = array();
+ foreach ($this->cache_vatrates as $cachevalue) {
+ if (empty($cachevalue['type_vat']) || $cachevalue['type_vat'] != $type_vat) {
+ $arrayofvatrates[] = $cachevalue;
+ }
+ }
+
+ $num = count($arrayofvatrates);
if ($num > 0) {
// Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '')
@@ -6560,7 +6574,7 @@ class Form
if ($defaulttx < 0 || dol_strlen($defaulttx) == 0) {
if (!getDolGlobalString('MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS')) {
// We take the last one found in list
- $defaulttx = $this->cache_vatrates[$num - 1]['txtva'];
+ $defaulttx = $arrayofvatrates[$num - 1]['txtva'];
} else {
// We will use the rate defined into MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS
$defaulttx = '';
@@ -6591,7 +6605,7 @@ class Form
}
$selectedfound = false;
- foreach ($this->cache_vatrates as $rate) {
+ foreach ($arrayofvatrates as $rate) {
// Keep only 0 if seller is not subject to VAT
if ($disabled && $rate['txtva'] != 0) {
continue;
diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php
index b69269e5c2b..c8a80fba260 100644
--- a/htdocs/core/tpl/objectline_create.tpl.php
+++ b/htdocs/core/tpl/objectline_create.tpl.php
@@ -442,10 +442,15 @@ if ($nolinesbefore) {
}
print '
';
// Unit price
diff --git a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql
index a0bb45ae935..9106971986d 100644
--- a/htdocs/install/mysql/migration/17.0.0-18.0.0.sql
+++ b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql
@@ -2,6 +2,7 @@
-- Be carefull to requests order.
-- This file must be loaded by calling /install/index.php page
-- when current version is 18.0.0 or higher.
+
--
-- To restrict request to Mysql version x.y minimum use -- VMYSQLx.y
-- To restrict request to Pgsql version x.y minimum use -- VPGSQLx.y
@@ -32,7 +33,7 @@
-- -- VPGSQL8.2 SELECT dol_util_rebuild_sequences();
--- v17
+-- Missing in v17 or lower
-- VMYSQL4.3 ALTER TABLE llx_emailcollector_emailcollector MODIFY COLUMN tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
@@ -86,7 +87,6 @@ ALTER TABLE llx_payment_salary MODIFY COLUMN datep datetime;
INSERT INTO llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1179, 117, 'I-28' , 28, 0, '0', 0, '0', 0, 'IGST', 1);
INSERT INTO llx_c_tva(rowid,fk_pays,code,taux,localtax1,localtax1_type,localtax2,localtax2_type,recuperableonly,note,active) values (1176, 117, 'C+S-18', 0, 9, '1', 9, '1', 0, 'CGST+SGST - Same state sales', 1);
-
ALTER TABLE llx_user ADD COLUMN flagdelsessionsbefore datetime DEFAULT NULL;
ALTER TABLE llx_website ADD COLUMN pageviews_previous_month BIGINT UNSIGNED DEFAULT 0;
diff --git a/htdocs/install/mysql/migration/19.0.0-20.0.0.sql b/htdocs/install/mysql/migration/19.0.0-20.0.0.sql
index 339f970c311..e6363ba41eb 100644
--- a/htdocs/install/mysql/migration/19.0.0-20.0.0.sql
+++ b/htdocs/install/mysql/migration/19.0.0-20.0.0.sql
@@ -198,3 +198,6 @@ CREATE TABLE llx_c_product_thirdparty_relation_type
active tinyint default 1 NOT NULL
) ENGINE = innodb;
+
+ALTER TABLE llx_c_tva ADD COLUMN type_vat smallint NOT NULL DEFAULT 0 AFTER fk_pays;
+
diff --git a/htdocs/install/mysql/tables/llx_c_tva.sql b/htdocs/install/mysql/tables/llx_c_tva.sql
index 496cda4161a..97c1d5e3071 100644
--- a/htdocs/install/mysql/tables/llx_c_tva.sql
+++ b/htdocs/install/mysql/tables/llx_c_tva.sql
@@ -20,20 +20,21 @@
create table llx_c_tva
(
- rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
- entity integer DEFAULT 1 NOT NULL,
- fk_pays integer NOT NULL,
- code varchar(10) DEFAULT '', -- a key to describe vat entry, for example FR20
- taux double NOT NULL,
- localtax1 varchar(20) NOT NULL DEFAULT '0',
- localtax1_type varchar(10) NOT NULL DEFAULT '0',
- localtax2 varchar(20) NOT NULL DEFAULT '0',
- localtax2_type varchar(10) NOT NULL DEFAULT '0',
- use_default tinyint DEFAULT 0, -- set to 1 to be the default vat when no vat defined on product
- recuperableonly integer NOT NULL DEFAULT 0,
- note varchar(128),
- active tinyint DEFAULT 1 NOT NULL,
- accountancy_code_sell varchar(32) DEFAULT NULL,
+ rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ entity integer DEFAULT 1 NOT NULL,
+ fk_pays integer NOT NULL,
+ type_vat smallint NOT NULL DEFAULT 0, -- 0: all, 1: sell, 2: purchase
+ code varchar(10) DEFAULT '', -- a key to describe vat entry, for example FR20
+ taux double NOT NULL,
+ localtax1 varchar(20) NOT NULL DEFAULT '0',
+ localtax1_type varchar(10) NOT NULL DEFAULT '0',
+ localtax2 varchar(20) NOT NULL DEFAULT '0',
+ localtax2_type varchar(10) NOT NULL DEFAULT '0',
+ use_default tinyint DEFAULT 0, -- set to 1 to be the default vat when no vat defined on product
+ recuperableonly integer NOT NULL DEFAULT 0,
+ note varchar(128),
+ active tinyint DEFAULT 1 NOT NULL,
+ accountancy_code_sell varchar(32) DEFAULT NULL,
accountancy_code_buy varchar(32) DEFAULT NULL
)ENGINE=innodb;
diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index 12ba6fc62e6..a1871dd23c8 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -1123,6 +1123,7 @@ VATIsUsedDesc=By default when creating prospects, invoices, orders etc. the Sale
VATIsNotUsedDesc=By default the proposed Sales tax is 0 which can be used for cases like associations, individuals or small companies.
VATIsUsedExampleFR=In France, it means companies or organizations having a real fiscal system (Simplified real or normal real). A system in which VAT is declared.
VATIsNotUsedExampleFR=In France, it means associations that are non Sales tax declared or companies, organizations or liberal professions that have chosen the micro enterprise fiscal system (Sales tax in franchise) and paid a franchise Sales tax without any Sales tax declaration. This choice will display the reference "Non applicable Sales tax - art-293B of CGI" on invoices.
+VATType=VAT type
##### Local Taxes #####
TypeOfSaleTaxes=Type of sales tax
LTRate=Rate
diff --git a/htdocs/product/price.php b/htdocs/product/price.php
index 86e896b3e9f..2d5c8468fc3 100644
--- a/htdocs/product/price.php
+++ b/htdocs/product/price.php
@@ -144,11 +144,12 @@ if (empty($reshook)) {
// We look into database using code (we can't use get_localtax() because it depends on buyer that is not known). Same in create product.
$vatratecode = $reg[1];
// Get record from code
- $sql = "SELECT t.rowid, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
+ $sql = "SELECT t.rowid, t.type_vat, t.code, t.recuperableonly, t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
$sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
$sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($mysoc->country_code)."'";
$sql .= " AND t.taux = ".((float) $tva_tx)." AND t.active = 1";
$sql .= " AND t.code = '".$db->escape($vatratecode)."'";
+ $sql .= " AND t.type_vat IN (0, 1)"; // Use only VAT rates type all or i.e. the sales type VAT rates.
$sql .= " AND t.entity IN (".getEntity('c_tva').")";
$resql = $db->query($sql);
if ($resql) {