From 219c34636fe86429fd3bf7468b6b8c51bfafed43 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 10 Jan 2023 04:30:02 +0100 Subject: [PATCH 1/9] VAT type : Field & migration --- .../install/mysql/migration/17.0.0-18.0.0.sql | 39 +++++++++++++++++++ htdocs/install/mysql/tables/llx_c_tva.sql | 29 +++++++------- 2 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 htdocs/install/mysql/migration/17.0.0-18.0.0.sql 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 new file mode 100644 index 00000000000..15e4b434e6d --- /dev/null +++ b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql @@ -0,0 +1,39 @@ +-- +-- Be carefull to requests order. +-- This file must be loaded by calling /install/index.php page +-- when current version is 17.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 +-- To rename a table: ALTER TABLE llx_table RENAME TO llx_table_new; +-- To add a column: ALTER TABLE llx_table ADD COLUMN newcol varchar(60) NOT NULL DEFAULT '0' AFTER existingcol; +-- To rename a column: ALTER TABLE llx_table CHANGE COLUMN oldname newname varchar(60); +-- To drop a column: ALTER TABLE llx_table DROP COLUMN oldname; +-- To change type of field: ALTER TABLE llx_table MODIFY COLUMN name varchar(60); +-- To drop a foreign key: ALTER TABLE llx_table DROP FOREIGN KEY fk_name; +-- To create a unique index ALTER TABLE llx_table ADD UNIQUE INDEX uk_table_field (field); +-- To drop an index: -- VMYSQL4.1 DROP INDEX nomindex on llx_table; +-- To drop an index: -- VPGSQL8.2 DROP INDEX nomindex; +-- To make pk to be auto increment (mysql): +-- -- VMYSQL4.3 ALTER TABLE llx_table ADD PRIMARY KEY(rowid); +-- -- VMYSQL4.3 ALTER TABLE llx_table CHANGE COLUMN rowid rowid INTEGER NOT NULL AUTO_INCREMENT; +-- To make pk to be auto increment (postgres): +-- -- VPGSQL8.2 CREATE SEQUENCE llx_table_rowid_seq OWNED BY llx_table.rowid; +-- -- VPGSQL8.2 ALTER TABLE llx_table ADD PRIMARY KEY (rowid); +-- -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN rowid SET DEFAULT nextval('llx_table_rowid_seq'); +-- -- VPGSQL8.2 SELECT setval('llx_table_rowid_seq', MAX(rowid)) FROM llx_table; +-- To set a field as NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NULL; +-- To set a field as NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name DROP NOT NULL; +-- To set a field as NOT NULL: -- VMYSQL4.3 ALTER TABLE llx_table MODIFY COLUMN name varchar(60) NOT NULL; +-- To set a field as NOT NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET NOT NULL; +-- To set a field as default NULL: -- VPGSQL8.2 ALTER TABLE llx_table ALTER COLUMN name SET DEFAULT NULL; +-- Note: fields with type BLOB/TEXT can't have default value. +-- To rebuild sequence for postgresql after insert by forcing id autoincrement fields: +-- -- VPGSQL8.2 SELECT dol_util_rebuild_sequences(); + + +-- Missing in v17 or lower + + +-- v18 +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 9bc77bb69ea..d16ec208ba4 100644 --- a/htdocs/install/mysql/tables/llx_c_tva.sql +++ b/htdocs/install/mysql/tables/llx_c_tva.sql @@ -1,7 +1,7 @@ -- ======================================================================== -- Copyright (C) 2005 Laurent Destailleur -- Copyright (C) 2010-2015 Juanjo Menent --- Copyright (C) 2011-2012 Alexandre Spangaro +-- Copyright (C) 2011-2023 Alexandre Spangaro -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by @@ -20,19 +20,20 @@ create table llx_c_tva ( - rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, - 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, + 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; From d5643423e412e7a244910578f3d3541ca91f9c39 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 10 Jan 2023 04:59:18 +0100 Subject: [PATCH 2/9] VAT type : Dict --- htdocs/admin/dict.php | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index d928931c9ab..cc338511811 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -8,7 +8,7 @@ * Copyright (C) 2011 Remy Younes * Copyright (C) 2012-2015 Marcos García * Copyright (C) 2012 Christophe Battarel - * Copyright (C) 2011-2022 Alexandre Spangaro + * Copyright (C) 2011-2023 Alexandre Spangaro * Copyright (C) 2015 Ferran Marcet * Copyright (C) 2016 Raphaël Doursenaud * Copyright (C) 2019-2022 Frédéric France @@ -208,7 +208,7 @@ $tabsql[6] = "SELECT a.id as rowid, a.code as code, a.libelle AS libelle, a.t $tabsql[7] = "SELECT a.id as rowid, a.code as code, a.libelle AS libelle, a.accountancy_code as accountancy_code, c.code as country_code, c.label as country, a.fk_pays as country_id, a.active FROM ".MAIN_DB_PREFIX."c_chargesociales AS a, ".MAIN_DB_PREFIX."c_country as c WHERE a.fk_pays=c.rowid and c.active=1"; $tabsql[8] = "SELECT t.id as rowid, t.code as code, t.libelle, t.fk_country as country_id, c.code as country_code, c.label as country, t.position, t.active FROM ".MAIN_DB_PREFIX."c_typent as t LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON t.fk_country=c.rowid"; $tabsql[9] = "SELECT c.code_iso as code, c.label, c.unicode, c.active FROM ".MAIN_DB_PREFIX."c_currencies AS c"; -$tabsql[10] = "SELECT t.rowid, t.code, t.taux, t.localtax1_type, t.localtax1, t.localtax2_type, t.localtax2, c.label as country, c.code as country_code, t.fk_pays as country_id, t.recuperableonly, t.note, t.active, t.accountancy_code_sell, t.accountancy_code_buy FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c WHERE t.fk_pays=c.rowid"; +$tabsql[10] = "SELECT t.rowid, t.type_vat, t.code, t.taux, t.localtax1_type, t.localtax1, t.localtax2_type, t.localtax2, c.label as country, c.code as country_code, t.fk_pays as country_id, t.recuperableonly, t.note, t.active, t.accountancy_code_sell, t.accountancy_code_buy FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c WHERE t.fk_pays=c.rowid"; $tabsql[11] = "SELECT t.rowid as rowid, t.element, t.source, t.code, t.libelle, t.position, t.active FROM ".MAIN_DB_PREFIX."c_type_contact AS t"; $tabsql[12] = "SELECT c.rowid as rowid, c.code, c.libelle, c.libelle_facture, c.deposit_percent, c.nbjour, c.type_cdr, c.decalage, c.active, c.sortorder, c.entity FROM ".MAIN_DB_PREFIX."c_payment_term AS c WHERE c.entity = ".getEntity($tabname[12]); $tabsql[13] = "SELECT c.id as rowid, c.code, c.libelle, c.type, c.active, c.entity FROM ".MAIN_DB_PREFIX."c_paiement AS c WHERE c.entity = ".getEntity($tabname[13]); @@ -302,7 +302,7 @@ $tabfield[6] = "code,libelle,type,color,position"; $tabfield[7] = "code,libelle,country,accountancy_code"; $tabfield[8] = "code,libelle,country_id,country".(!empty($conf->global->SOCIETE_SORT_ON_TYPEENT) ? ',position' : ''); $tabfield[9] = "code,label,unicode"; -$tabfield[10] = "country_id,country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; +$tabfield[10] = "country_id,country,type_vat,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; $tabfield[11] = "element,source,code,libelle,position"; $tabfield[12] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder,entity"; $tabfield[13] = "code,libelle,type,entity"; @@ -349,7 +349,7 @@ $tabfieldvalue[6] = "code,libelle,type,color,position"; $tabfieldvalue[7] = "code,libelle,country,accountancy_code"; $tabfieldvalue[8] = "code,libelle,country".(!empty($conf->global->SOCIETE_SORT_ON_TYPEENT) ? ',position' : ''); $tabfieldvalue[9] = "code,label,unicode"; -$tabfieldvalue[10] = "country,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; +$tabfieldvalue[10] = "country,type_vat,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; $tabfieldvalue[11] = "element,source,code,libelle,position"; $tabfieldvalue[12] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder"; $tabfieldvalue[13] = "code,libelle,type"; @@ -396,7 +396,7 @@ $tabfieldinsert[6] = "code,libelle,type,color,position"; $tabfieldinsert[7] = "code,libelle,fk_pays,accountancy_code"; $tabfieldinsert[8] = "code,libelle,fk_country".(!empty($conf->global->SOCIETE_SORT_ON_TYPEENT) ? ',position' : ''); $tabfieldinsert[9] = "code_iso,label,unicode"; -$tabfieldinsert[10] = "fk_pays,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; +$tabfieldinsert[10] = "fk_pays,type_vat,code,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note"; $tabfieldinsert[11] = "element,source,code,libelle,position"; $tabfieldinsert[12] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder,entity"; $tabfieldinsert[13] = "code,libelle,type,entity"; @@ -656,6 +656,13 @@ if ($id == 11) { ); } +// Define type_vatList (used for dictionary "llx_c_tva") +$type_vatList = array( + "0" => $langs->trans("All"), + "1" => $langs->trans("Sell"), + "2" => $langs->trans("Buy") +); + // Define localtax_typeList (used for dictionary "llx_c_tva") $localtax_typeList = array( "0" => $langs->trans("No"), @@ -1327,6 +1334,9 @@ if ($id > 0) { } $class = 'center'; } + if ($value == 'type_vat') { + $valuetoshow = $langs->trans("VATType"); $class = "center"; $sortable = 0; + } if ($value == 'localtax1_type') { $valuetoshow = $langs->trans("UseLocalTax")." 2"; $class = "center"; $sortable = 0; } @@ -1700,6 +1710,9 @@ if ($id > 0) { $cssprefix = 'center '; } + if ($value == 'type_vat') { + $valuetoshow = $langs->trans("VATType"); $cssprefix = "center "; $sortable = 0; + } if ($value == 'localtax1_type') { $valuetoshow = $langs->trans("UseLocalTax")." 2"; $cssprefix = "center "; $sortable = 0; } @@ -2057,6 +2070,13 @@ if ($id > 0) { $valuetoshow = ($obj->code && $key != 'SizeUnit'.strtolower($obj->unit) ? $key : $obj->{$value}); } elseif ($value == 'localtax1' || $value == 'localtax2') { $class = "center"; + } elseif ($value == 'type_vat') { + if ($obj->type_vat != 0) { + $valuetoshow = $type_vatList[$valuetoshow]; + } else { + $valuetoshow = $langs->transnoentitiesnoconv("All"); + } + $class = "center"; } elseif ($value == 'localtax1_type') { if ($obj->localtax1 != 0) { $valuetoshow = $localtax_typeList[$valuetoshow]; @@ -2127,7 +2147,7 @@ if ($id > 0) { if (in_array($value, array('nbjour', 'decalage', 'pos', 'position', 'deposit_percent'))) { $class .= ' right'; } - if (in_array($value, array('localtax1_type', 'localtax2_type'))) { + if (in_array($value, array('type_vat', 'localtax1_type', 'localtax2_type'))) { $class .= ' nowraponall'; } if (in_array($value, array('use_default', 'fk_parent', 'sortorder'))) { @@ -2347,7 +2367,7 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') global $conf, $langs, $db, $mysoc; global $form; global $region_id; - global $elementList, $sourceList, $localtax_typeList; + global $elementList, $sourceList, $localtax_typeList, $type_vatList; $formadmin = new FormAdmin($db); $formcompany = new FormCompany($db); @@ -2480,6 +2500,11 @@ function fieldList($fieldlist, $obj = '', $tabname = '', $context = '') ); print $form->selectarray('unit', $units, (!empty($obj->{$value}) ? $obj->{$value}:''), 0, 0, 0); print ''; + } elseif ($value == 'type_vat') { + // VAT type 0: all, 1: sell, 2: purchase + print ''; + print $form->selectarray($value, $type_vatList, (!empty($obj->{$value}) ? $obj->{$value}:'')); + print ''; } elseif ($value == 'localtax1_type' || $value == 'localtax2_type') { // Le type de taxe locale print ''; From fa54bf60a95b37879f1c051bada8caeee9358284 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 10 Jan 2023 04:59:35 +0100 Subject: [PATCH 3/9] VAT type : Lang --- htdocs/langs/en_US/admin.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 62176a37c41..643a0caf8a2 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1096,6 +1096,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 From 9caceb6d4f938faac9991165fbadf1941eb93908 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 10 Jan 2023 04:59:54 +0100 Subject: [PATCH 4/9] VAT type : Form --- htdocs/core/class/html.form.class.php | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index da6339bdaec..8eb69de282b 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -15,7 +15,7 @@ * Copyright (C) 2012-2016 Marcos García * Copyright (C) 2012 Cedric Salvador * Copyright (C) 2012-2015 Raphaël Doursenaud - * Copyright (C) 2014-2020 Alexandre Spangaro + * Copyright (C) 2014-2023 Alexandre Spangaro * Copyright (C) 2018-2022 Ferran Marcet * Copyright (C) 2018-2021 Frédéric France * Copyright (C) 2018 Nicolas ZABOURI @@ -6129,9 +6129,10 @@ class Form * Load into the cache vat rates of a country * * @param string $country_code Country code with quotes ("'CA'", or "'CA,IN,...'") + * @param int $type_vat 0=All type, 1=VAT rate sale, 2=VAT rate purchase * @return int Nb of loaded lines, 0 if already loaded, <0 if KO */ - public function load_cache_vatrates($country_code) + public function load_cache_vatrates($country_code, $type_vat = 0) { // phpcs:enable global $langs; @@ -6143,10 +6144,13 @@ 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 = "SELECT DISTINCT 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"; + if ($type_vat > 0) { + $sql .= " AND t.type_vat IN (0, ".((int) $type_vat).")"; + } $sql .= " AND c.code IN (".$this->db->sanitize($country_code, 1).")"; $sql .= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC"; @@ -6156,10 +6160,11 @@ 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]['rowid'] = $obj->rowid; + $this->cache_vatrates[$i]['type_vat'] = $obj->type_vat; + $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; @@ -6214,9 +6219,10 @@ class Form * Sinon la TVA proposee par defaut=0. Fin de regle. * @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 = '', $societe_acheteuse = '', $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0) + public function load_tva($htmlname = 'tauxtva', $selectedrate = '', $societe_vendeuse = '', $societe_acheteuse = '', $idprod = 0, $info_bits = 0, $type = '', $options_only = false, $mode = 0, $type_vat = 0) { // phpcs:enable global $langs, $conf, $mysoc; @@ -6279,7 +6285,7 @@ class Form } // Now we get list - $num = $this->load_cache_vatrates($code_country); // If no vat defined, return -1 with message into this->error + $num = $this->load_cache_vatrates($code_country, $type_vat); // If no vat defined, return -1 with message into this->error if ($num > 0) { // Definition du taux a pre-selectionner (si defaulttx non force et donc vaut -1 ou '') From a86a712821cf5dd01aa994f6c4d70fe0fa9afc3e Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 10 Jan 2023 05:00:24 +0100 Subject: [PATCH 5/9] VAT type : Card --- htdocs/core/tpl/objectline_create.tpl.php | 7 ++++++- htdocs/core/tpl/objectline_edit.tpl.php | 11 ++++++++--- htdocs/expensereport/card.php | 4 ++-- htdocs/product/price.php | 5 +++-- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index c0382a39de4..47ca4607324 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -389,10 +389,15 @@ if ($nolinesbefore) { '; $coldisplay++; + if ($object->element == 'propal' || $object->element == 'commande' || $object->element == 'facture' || $object->element == 'facturerec') { + $type_tva = 1; + } else if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { + $type_tva = 2; + } if ($seller->tva_assuj == "0") { echo ''.vatrate(0, true); } else { - echo $form->load_tva('tva_tx', (GETPOSTISSET("tva_tx") ? GETPOST("tva_tx", 'alpha', 2) : -1), $seller, $buyer, 0, 0, '', false, 1); + echo $form->load_tva('tva_tx', (GETPOSTISSET("tva_tx") ? GETPOST("tva_tx", 'alpha', 2) : -1), $seller, $buyer, 0, 0, '', false, 1, $type_tva); } ?> diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index 5520215d89a..c5cb1fe6dcb 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -1,11 +1,11 @@ +/* Copyright (C) 2010-2012 Regis Houssin * Copyright (C) 2010-2022 Laurent Destailleur * Copyright (C) 2012 Christophe Battarel * Copyright (C) 2012 Cédric Salvador * Copyright (C) 2012-2014 Raphaël Doursenaud * Copyright (C) 2013 Florian Henry - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018 Frédéric France * Copyright (C) 2022 OpenDSI * * This program is free software; you can redistribute it and/or modify @@ -203,9 +203,14 @@ $coldisplay++; // VAT Rate $coldisplay++; + if ($object->element == 'propal' || $object->element == 'commande' || $object->element == 'facture' || $object->element == 'facturerec') { + $type_tva = 1; + } else if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { + $type_tva = 2; + } if (!$situationinvoicelinewithparent) { print ''; - print $form->load_tva('tva_tx', GETPOSTISSET('tva_tx') ? GETPOST('tva_tx', 'alpha') : ($line->tva_tx.($line->vat_src_code ? (' ('.$line->vat_src_code.')') : '')), $seller, $buyer, 0, $line->info_bits, $line->product_type, false, 1); + print $form->load_tva('tva_tx', GETPOSTISSET('tva_tx') ? GETPOST('tva_tx', 'alpha') : ($line->tva_tx.($line->vat_src_code ? (' ('.$line->vat_src_code.')') : '')), $seller, $buyer, 0, $line->info_bits, $line->product_type, false, 1, $type_tva); print ''; } else { print '%'; diff --git a/htdocs/expensereport/card.php b/htdocs/expensereport/card.php index f6aa14865ec..413638da811 100644 --- a/htdocs/expensereport/card.php +++ b/htdocs/expensereport/card.php @@ -2,7 +2,7 @@ /* Copyright (C) 2003 Rodolphe Quiedeville * Copyright (C) 2004-2020 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin - * Copyright (C) 2015-2022 Alexandre Spangaro + * Copyright (C) 2015-2023 Alexandre Spangaro * Copyright (C) 2017 Ferran Marcet * Copyright (C) 2018 Frédéric France * @@ -2337,7 +2337,7 @@ if ($action == 'create') { // VAT $selectedvat = price2num($line->vatrate).(!empty($line->vat_src_code) ? ' ('.$line->vat_src_code.')' : ''); print ''; - print $form->load_tva('vatrate', (GETPOSTISSET("vatrate") ? GETPOST("vatrate") : $selectedvat), $mysoc, '', 0, 0, '', false, 1); + print $form->load_tva('vatrate', (GETPOSTISSET("vatrate") ? GETPOST("vatrate") : $selectedvat), $mysoc, '', 0, 0, '', false, 1, 2); print ''; // Unit price diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 5a386792d1c..e77b31e63fa 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -8,7 +8,7 @@ * Copyright (C) 2014-2018 Juanjo Menent * Copyright (C) 2014-2019 Philippe Grand * Copyright (C) 2014 Ion agorria - * Copyright (C) 2015 Alexandre Spangaro + * Copyright (C) 2015-2023 Alexandre Spangaro * Copyright (C) 2015 Marcos García * Copyright (C) 2016 Ferran Marcet * Copyright (C) 2018-2020 Frédéric France @@ -141,11 +141,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 = 1"; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); From 83cdd8a759de10615f073ece560a5bc179c2c6c5 Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Tue, 10 Jan 2023 05:02:08 +0100 Subject: [PATCH 6/9] VAT type : style errors --- htdocs/core/tpl/objectline_create.tpl.php | 2 +- htdocs/core/tpl/objectline_edit.tpl.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 47ca4607324..98bdec7d10e 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -391,7 +391,7 @@ if ($nolinesbefore) { $coldisplay++; if ($object->element == 'propal' || $object->element == 'commande' || $object->element == 'facture' || $object->element == 'facturerec') { $type_tva = 1; - } else if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { + } elseif ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { $type_tva = 2; } if ($seller->tva_assuj == "0") { diff --git a/htdocs/core/tpl/objectline_edit.tpl.php b/htdocs/core/tpl/objectline_edit.tpl.php index c5cb1fe6dcb..c515e121ece 100644 --- a/htdocs/core/tpl/objectline_edit.tpl.php +++ b/htdocs/core/tpl/objectline_edit.tpl.php @@ -205,7 +205,7 @@ $coldisplay++; $coldisplay++; if ($object->element == 'propal' || $object->element == 'commande' || $object->element == 'facture' || $object->element == 'facturerec') { $type_tva = 1; - } else if ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { + } elseif ($object->element == 'supplier_proposal' || $object->element == 'order_supplier' || $object->element == 'invoice_supplier' || $object->element == 'invoice_supplier_rec') { $type_tva = 2; } if (!$situationinvoicelinewithparent) { From d91cc979a262349e912bde4a540f02c8347f6c8c Mon Sep 17 00:00:00 2001 From: Alexandre SPANGARO Date: Wed, 26 Apr 2023 06:46:02 +0200 Subject: [PATCH 7/9] FIX Type of VAT type (Want 0 All + 1 Sales) --- htdocs/product/price.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/price.php b/htdocs/product/price.php index 091e208ab50..e9c40510790 100644 --- a/htdocs/product/price.php +++ b/htdocs/product/price.php @@ -146,7 +146,7 @@ if (empty($reshook)) { $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 = 1"; + $sql .= " AND t.type_vat IN (0, 1)"; // Use only VAT rates type all or i.e. the sales type VAT rates. $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); From 4957eacfa671dfd3d445e3b3df76aeb7c16f6d33 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Jan 2024 11:45:00 +0100 Subject: [PATCH 8/9] Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop --- htdocs/admin/dict.php | 337 ++---------------------------------------- 1 file changed, 9 insertions(+), 328 deletions(-) diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index 1c426b63cc5..98fd4961592 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -768,14 +768,14 @@ if (empty($reshook)) { continue; // For a column name 'sortorder', we use the field name 'position' } if ((!GETPOSTISSET($value) || GETPOST($value) == '') - && ( - !in_array($value, array('decalage', 'module', 'accountancy_code', 'accountancy_code_sell', 'accountancy_code_buy', 'tracking', 'picto', 'deposit_percent')) // Fields that are not mandatory + && ( + !in_array($value, array('decalage', 'module', 'accountancy_code', 'accountancy_code_sell', 'accountancy_code_buy', 'tracking', 'picto', 'deposit_percent')) // Fields that are not mandatory && ($id != 10 || ($value != 'code' && $value != 'note')) // Field code and note is not mandatory for dictionary table 10 ) ) { - $ok = 0; - $fieldnamekey = $value; - // We take translate key of field + $ok = 0; + $fieldnamekey = $value; + // We take translate key of field if ($fieldnamekey == 'libelle' || ($fieldnamekey == 'label')) { $fieldnamekey = 'Label'; } @@ -828,7 +828,7 @@ if (empty($reshook)) { $fieldnamekey = 'UseByDefault'; } - setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities($fieldnamekey)), null, 'errors'); + setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentities($fieldnamekey)), null, 'errors'); } } // Other special checks @@ -1353,325 +1353,6 @@ if ($id > 0) { print "
\n"; } - // Form to add a new line - if ($tabname[$id]) { - $withentity = null; - - $fieldlist = explode(',', $tabfield[$id]); - - print '
'; - print ''; - - // Line for title - print ''; - $tdsoffields = ''; - foreach ($fieldlist as $field => $value) { - if ($value == 'entity') { - $withentity = getEntity($tabname[$id]); - continue; - } - - // Define field friendly name from its technical name - $valuetoshow = ucfirst($value); // Par defaut - $valuetoshow = $langs->trans($valuetoshow); // try to translate - $class = ''; - - if ($value == 'pos') { - $valuetoshow = $langs->trans("Position"); $class = 'right'; - } - if ($value == 'source') { - $valuetoshow = $langs->trans("Contact"); - } - if ($value == 'price') { - $valuetoshow = $langs->trans("PriceUHT"); - } - if ($value == 'taux') { - if ($tabname[$id] != "c_revenuestamp") { - $valuetoshow = $langs->trans("Rate"); - } else { - $valuetoshow = $langs->trans("Amount"); - } - $class = 'center'; - } - if ($value == 'type_vat') { - $valuetoshow = $langs->trans("VATType"); $class = "center"; $sortable = 0; - } - if ($value == 'localtax1_type') { - $valuetoshow = $langs->trans("UseLocalTax")." 2"; $class = "center"; $sortable = 0; - } - if ($value == 'localtax1') { - $valuetoshow = $langs->trans("RateOfTaxN", '2'); $class = "center"; - } - if ($value == 'localtax2_type') { - $valuetoshow = $langs->trans("UseLocalTax")." 3"; $class = "center"; $sortable = 0; - } - if ($value == 'localtax2') { - $valuetoshow = $langs->trans("RateOfTaxN", '3'); $class = "center"; - } - if ($value == 'organization') { - $valuetoshow = $langs->trans("Organization"); - } - if ($value == 'lang') { - $valuetoshow = $langs->trans("Language"); - } - if ($value == 'type') { - if ($tabname[$id] == "c_paiement") { - $valuetoshow = $form->textwithtooltip($langs->trans("Type"), $langs->trans("TypePaymentDesc"), 2, 1, img_help(1, '')); - } else { - $valuetoshow = $langs->trans("Type"); - } - } - if ($value == 'code') { - $valuetoshow = $langs->trans("Code"); $class = 'maxwidth100'; - } - if ($value == 'libelle' || $value == 'label') { - $valuetoshow = $form->textwithtooltip($langs->trans("Label"), $langs->trans("LabelUsedByDefault"), 2, 1, img_help(1, '')); - } - if ($value == 'libelle_facture') { - $valuetoshow = $form->textwithtooltip($langs->trans("LabelOnDocuments"), $langs->trans("LabelUsedByDefault"), 2, 1, img_help(1, '')); - } - if ($value == 'deposit_percent') { - $valuetoshow = $langs->trans('DepositPercent'); - $class = 'right'; - } - if ($value == 'country') { - if (in_array('region_id', $fieldlist)) { - print ''; continue; - } // For region page, we do not show the country input - $valuetoshow = $langs->trans("Country"); - } - if ($value == 'recuperableonly') { - $valuetoshow = $langs->trans("NPR"); $class = "center"; - } - if ($value == 'nbjour') { - $valuetoshow = $langs->trans("NbOfDays"); - $class = 'right'; - } - if ($value == 'type_cdr') { - $valuetoshow = $langs->trans("AtEndOfMonth"); $class = "center"; - } - if ($value == 'decalage') { - $valuetoshow = $langs->trans("Offset"); - $class = 'right'; - } - if ($value == 'width' || $value == 'nx') { - $valuetoshow = $langs->trans("Width"); - } - if ($value == 'height' || $value == 'ny') { - $valuetoshow = $langs->trans("Height"); - } - if ($value == 'unit' || $value == 'metric') { - $valuetoshow = $langs->trans("MeasuringUnit"); - } - if ($value == 'region_id' || $value == 'country_id') { - $valuetoshow = ''; - } - if ($value == 'accountancy_code') { - $valuetoshow = $langs->trans("AccountancyCode"); - } - if ($value == 'accountancy_code_sell') { - $valuetoshow = $langs->trans("AccountancyCodeSell"); - } - if ($value == 'accountancy_code_buy') { - $valuetoshow = $langs->trans("AccountancyCodeBuy"); - } - if ($value == 'pcg_version' || $value == 'fk_pcg_version') { - $valuetoshow = $langs->trans("Pcg_version"); - } - if ($value == 'account_parent') { - $valuetoshow = $langs->trans("Accountparent"); - } - if ($value == 'pcg_type') { - $valuetoshow = $langs->trans("Pcg_type"); - } - if ($value == 'pcg_subtype') { - $valuetoshow = $langs->trans("Pcg_subtype"); - } - if ($value == 'sortorder') { - $valuetoshow = $langs->trans("SortOrder"); - $class = 'center'; - } - if ($value == 'short_label') { - $valuetoshow = $langs->trans("ShortLabel"); - } - if ($value == 'fk_parent') { - $valuetoshow = $langs->trans("ParentID"); $class = 'center'; - } - if ($value == 'range_account') { - $valuetoshow = $langs->trans("Range"); - } - if ($value == 'sens') { - $valuetoshow = $langs->trans("Sens"); - } - if ($value == 'category_type') { - $valuetoshow = $langs->trans("Calculated"); - } - if ($value == 'formula') { - $valuetoshow = $langs->trans("Formula"); - } - if ($value == 'paper_size') { - $valuetoshow = $langs->trans("PaperSize"); - } - if ($value == 'orientation') { - $valuetoshow = $langs->trans("Orientation"); - } - if ($value == 'leftmargin') { - $valuetoshow = $langs->trans("LeftMargin"); - } - if ($value == 'topmargin') { - $valuetoshow = $langs->trans("TopMargin"); - } - if ($value == 'spacex') { - $valuetoshow = $langs->trans("SpaceX"); - } - if ($value == 'spacey') { - $valuetoshow = $langs->trans("SpaceY"); - } - if ($value == 'font_size') { - $valuetoshow = $langs->trans("FontSize"); - } - if ($value == 'custom_x') { - $valuetoshow = $langs->trans("CustomX"); - } - if ($value == 'custom_y') { - $valuetoshow = $langs->trans("CustomY"); - } - if ($value == 'percent') { - $valuetoshow = $langs->trans("Percentage"); - } - if ($value == 'affect') { - $valuetoshow = $langs->trans("WithCounter"); - } - if ($value == 'delay') { - $valuetoshow = $langs->trans("NoticePeriod"); - } - if ($value == 'newbymonth') { - $valuetoshow = $langs->trans("NewByMonth"); - } - if ($value == 'fk_tva') { - $valuetoshow = $langs->trans("VAT"); - } - if ($value == 'range_ik') { - $valuetoshow = $langs->trans("RangeIk"); - } - if ($value == 'fk_c_exp_tax_cat') { - $valuetoshow = $langs->trans("CarCategory"); - } - if ($value == 'revenuestamp_type') { - $valuetoshow = $langs->trans('TypeOfRevenueStamp'); - } - if ($value == 'use_default') { - $valuetoshow = $langs->trans('Default'); $class = 'center'; - } - if ($value == 'unit_type') { - $valuetoshow = $langs->trans('TypeOfUnit'); - } - if ($value == 'public' && $tablib[$id] == 'TicketDictCategory') { - $valuetoshow = $langs->trans('TicketGroupIsPublic'); $class = 'center'; - } - if ($value == 'block_if_negative') { - $valuetoshow = $langs->trans('BlockHolidayIfNegative'); - } - if ($value == 'type_duration') { - $valuetoshow = $langs->trans('Unit'); - } - - if ($id == 2) { // Special case for state page - if ($value == 'region_id') { - $valuetoshow = ' '; $showfield = 1; - } - if ($value == 'region') { - $valuetoshow = $langs->trans("Country").'/'.$langs->trans("Region"); $showfield = 1; - } - } - - if ($valuetoshow != '') { - $tooltiphelp = (isset($tabcomplete[$tabname[$id]]['help'][$value]) ? $tabcomplete[$tabname[$id]]['help'][$value] : ''); - - $tdsoffields .= ''; - if ($tooltiphelp && preg_match('/^http(s*):/i', $tooltiphelp)) { - $tdsoffields .= ''.$valuetoshow.' '.img_help(1, $valuetoshow).''; - } elseif ($tooltiphelp) { - $tdsoffields .= $form->textwithpicto($valuetoshow, $tooltiphelp); - } else { - $tdsoffields .= $valuetoshow; - } - $tdsoffields .= ''; - } - } - - if ($id == 4) { - $tdsoffields .= ''; - $tdsoffields .= ''; - } - $tdsoffields .= ''; - $tdsoffields .= ''; - $tdsoffields .= ''; - $tdsoffields .= ''; - - print $tdsoffields; - - - // Line to enter new values - print ''; - print ''; - - $obj = new stdClass(); - // If data was already input, we define them in obj to populate input fields. - if (GETPOST('actionadd')) { - foreach ($fieldlist as $key => $val) { - if (GETPOST($val) != '') { - $obj->$val = GETPOST($val); - } - } - } - - $tmpaction = 'create'; - $parameters = array('fieldlist'=>$fieldlist, 'tabname'=>$tabname[$id]); - $reshook = $hookmanager->executeHooks('createDictionaryFieldlist', $parameters, $obj, $tmpaction); // Note that $action and $object may have been modified by some hooks - $error = $hookmanager->error; $errors = $hookmanager->errors; - - if ($id == 3) { - unset($fieldlist[2]); // Remove field ??? if dictionary Regions - } - - if (empty($reshook)) { - fieldList($fieldlist, $obj, $tabname[$id], 'add'); - } - - if ($id == 4) { - print ''; - print ''; - } - print ''; - - print ""; - - print '
 '; - $tdsoffields .= ''; - if (!is_null($withentity)) { - $tdsoffields .= ''; - } - $tdsoffields .= '
'; - if ($action != 'edit') { - print ''; - } else { - print ''; - } - print '
'; - print '
'; - } - - print ''; - - - print '
'; - - - print '
'; - print ''; - print ''; - // List of available record in database dol_syslog("htdocs/admin/dict", LOG_DEBUG); @@ -1684,9 +1365,9 @@ if ($id > 0) { $newcardbutton = ''; /*$newcardbutton .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-bars imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ((empty($mode) || $mode == 'common') ? 2 : 1), array('morecss'=>'reposition')); - $newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss'=>'reposition')); - $newcardbutton .= dolGetButtonTitleSeparator(); - */ + $newcardbutton .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=kanban'.preg_replace('/(&|\?)*mode=[^&]+/', '', $param), '', ($mode == 'kanban' ? 2 : 1), array('morecss'=>'reposition')); + $newcardbutton .= dolGetButtonTitleSeparator(); + */ $newcardbutton .= dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/admin/dict.php?action=create'.$param.'&backtopage='.urlencode($_SERVER['PHP_SELF']), '', $permissiontoadd); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'tools', 0, $newcardbutton, '', $listlimit, 1, 0, 1); From 1647e4f133692fe35170980b37f3acb44c570c19 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 11 Jan 2024 12:38:01 +0100 Subject: [PATCH 9/9] Debug the filter on VAT type --- htdocs/core/class/html.form.class.php | 66 +++++++++++-------- .../install/mysql/migration/17.0.0-18.0.0.sql | 2 - .../install/mysql/migration/19.0.0-20.0.0.sql | 3 + htdocs/install/mysql/tables/llx_c_tva.sql | 2 +- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 88102b987f2..0eb7f943811 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6372,13 +6372,12 @@ 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,...'") - * @param int $type_vat 0=All type, 1=VAT rate sale, 2=VAT rate purchase * @return int Nb of loaded lines, 0 if already loaded, <0 if KO */ - public function load_cache_vatrates($country_code, $type_vat = 0) + public function load_cache_vatrates($country_code) { // phpcs:enable global $langs, $user; @@ -6390,13 +6389,10 @@ class Form dol_syslog(__METHOD__, LOG_DEBUG); - $sql = "SELECT DISTINCT t.rowid, t.type_vat, t.code, t.taux, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.recuperableonly"; + $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"; - if ($type_vat > 0) { - $sql .= " AND t.type_vat IN (0, ".((int) $type_vat).")"; - } $sql .= " AND t.entity IN (".getEntity('c_tva').")"; $sql .= " AND c.code IN (" . $this->db->sanitize($country_code, 1) . ")"; $sql .= " ORDER BY t.code ASC, t.taux ASC, t.recuperableonly ASC"; @@ -6408,17 +6404,18 @@ class Form for ($i = 0; $i < $num; $i++) { $obj = $this->db->fetch_object($resql); - $this->cache_vatrates[$i]['rowid'] = $obj->rowid; - $this->cache_vatrates[$i]['type_vat'] = $obj->type_vat; - $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; @@ -6432,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[$i] = $tmparray; } return $num; @@ -6468,12 +6467,12 @@ class Form * @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. + * 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 @@ -6541,8 +6540,17 @@ class Form } } - // Now we get list - $num = $this->load_cache_vatrates($code_country, $type_vat); // 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 '') @@ -6566,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 = ''; @@ -6597,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/install/mysql/migration/17.0.0-18.0.0.sql b/htdocs/install/mysql/migration/17.0.0-18.0.0.sql index 240be18d2f5..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 @@ -87,8 +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_c_tva ADD COLUMN type_vat smallint NOT NULL DEFAULT '0' AFTER fk_pays; - 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 6193384cecb..97c1d5e3071 100644 --- a/htdocs/install/mysql/tables/llx_c_tva.sql +++ b/htdocs/install/mysql/tables/llx_c_tva.sql @@ -23,7 +23,7 @@ create table llx_c_tva 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 + 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',