Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEW VAT by state #31628

Merged
merged 9 commits into from
Nov 11, 2024
59 changes: 49 additions & 10 deletions htdocs/admin/dict.php
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@
$tabsql[DICT_CHARGESOCIALES] = "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[DICT_TYPENT] = "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[DICT_CURRENCIES] = "SELECT c.code_iso as code, c.label, c.unicode, c.active FROM ".MAIN_DB_PREFIX."c_currencies AS c";
$tabsql[DICT_TVA] = "SELECT t.rowid, t.entity, t.code, t.type_vat, 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 AND t.entity IN (".getEntity($tabname[DICT_TVA]).")";
$tabsql[DICT_TVA] = "SELECT t.rowid, t.entity, t.code, t.type_vat, 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.fk_department_buyer as department_buyer_id, db.nom as department_buyer, t.recuperableonly, t.note, t.active, t.accountancy_code_sell, t.accountancy_code_buy FROM ".MAIN_DB_PREFIX."c_tva as t INNER JOIN ".MAIN_DB_PREFIX."c_country as c ON t.fk_pays = c.rowid LEFT JOIN ".MAIN_DB_PREFIX."c_departements as db ON t.fk_department_buyer = db.rowid WHERE t.entity IN (".getEntity($tabname[DICT_TVA]).")";
$tabsql[DICT_TYPE_CONTACT] = "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[DICT_PAYMENT_TERM] = "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 IN (".getEntity($tabname[DICT_PAYMENT_TERM]).")";
$tabsql[DICT_PAIEMENT] = "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 IN (".getEntity($tabname[DICT_PAIEMENT]).")";
Expand Down Expand Up @@ -322,7 +322,7 @@
$tabsqlsort[DICT_CHARGESOCIALES] = "c.label ASC, a.code ASC, a.libelle ASC";
$tabsqlsort[DICT_TYPENT] = "country DESC,".(getDolGlobalString('SOCIETE_SORT_ON_TYPEENT') ? ' t.position ASC,' : '')." libelle ASC";
$tabsqlsort[DICT_CURRENCIES] = "label ASC";
$tabsqlsort[DICT_TVA] = "country ASC, code ASC, taux ASC, recuperableonly ASC, localtax1 ASC, localtax2 ASC";
$tabsqlsort[DICT_TVA] = "country ASC, department_buyer ASC, code ASC, taux ASC, recuperableonly ASC, localtax1 ASC, localtax2 ASC";
$tabsqlsort[DICT_TYPE_CONTACT] = "t.element ASC, t.source ASC, t.position ASC, t.code ASC";
$tabsqlsort[DICT_PAYMENT_TERM] = "sortorder ASC, code ASC";
$tabsqlsort[DICT_PAIEMENT] = "code ASC";
Expand Down Expand Up @@ -369,7 +369,7 @@
$tabfield[DICT_CHARGESOCIALES] = "code,libelle,country,accountancy_code";
$tabfield[DICT_TYPENT] = "code,libelle,country_id,country".(getDolGlobalString('SOCIETE_SORT_ON_TYPEENT') ? ',position' : '');
$tabfield[DICT_CURRENCIES] = "code,label,unicode";
$tabfield[DICT_TVA] = "country_id,country,code,type_vat,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
$tabfield[DICT_TVA] = "country_id,country,department_buyer_id,department_buyer,code,type_vat,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
$tabfield[DICT_TYPE_CONTACT] = "element,source,code,libelle,position";
$tabfield[DICT_PAYMENT_TERM] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder";
$tabfield[DICT_PAIEMENT] = "code,libelle,type";
Expand Down Expand Up @@ -416,7 +416,7 @@
$tabfieldvalue[DICT_CHARGESOCIALES] = "code,libelle,country,accountancy_code";
$tabfieldvalue[DICT_TYPENT] = "code,libelle,country".(getDolGlobalString('SOCIETE_SORT_ON_TYPEENT') ? ',position' : '');
$tabfieldvalue[DICT_CURRENCIES] = "code,label,unicode";
$tabfieldvalue[DICT_TVA] = "country,code,type_vat,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
$tabfieldvalue[DICT_TVA] = "country,department_buyer_id,code,type_vat,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note";
$tabfieldvalue[DICT_TYPE_CONTACT] = "element,source,code,libelle,position";
$tabfieldvalue[DICT_PAYMENT_TERM] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder";
$tabfieldvalue[DICT_PAIEMENT] = "code,libelle,type";
Expand Down Expand Up @@ -463,7 +463,7 @@
$tabfieldinsert[DICT_CHARGESOCIALES] = "code,libelle,fk_pays,accountancy_code";
$tabfieldinsert[DICT_TYPENT] = "code,libelle,fk_country".(getDolGlobalString('SOCIETE_SORT_ON_TYPEENT') ? ',position' : '');
$tabfieldinsert[DICT_CURRENCIES] = "code_iso,label,unicode";
$tabfieldinsert[DICT_TVA] = "fk_pays,code,type_vat,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note,entity";
$tabfieldinsert[DICT_TVA] = "fk_pays,fk_department_buyer,code,type_vat,taux,localtax1_type,localtax1,localtax2_type,localtax2,recuperableonly,accountancy_code_sell,accountancy_code_buy,note,entity";
$tabfieldinsert[DICT_TYPE_CONTACT] = "element,source,code,libelle,position";
$tabfieldinsert[DICT_PAYMENT_TERM] = "code,libelle,libelle_facture,deposit_percent,nbjour,type_cdr,decalage,sortorder,entity";
$tabfieldinsert[DICT_PAIEMENT] = "code,libelle,type,entity";
Expand Down Expand Up @@ -810,6 +810,14 @@
if ($value == 'country' && in_array($tablib[$id], array('DictionaryPublicHolidays', 'DictionaryCanton', 'DictionaryCompanyType', 'DictionaryHolidayTypes', 'DictionaryRevenueStamp'))) {
continue; // For some pages, country is not mandatory
}
// Discard check of mandatory fields for department buyer id for some tables (only for add action)
if (GETPOST('actionadd') && $value == 'department_buyer_id' && $tablib[$id] == 'DictionaryVAT') {
continue; // For some pages, department buyer id is not mandatory
}
// Discard check of mandatory fields for department buyer for some tables
if ($value == 'department_buyer' && $tablib[$id] == 'DictionaryVAT') {
continue; // For some pages, department buyer is not mandatory
}
// Discard check of mandatory fields for other fields
if ($value == 'localtax1' && !GETPOST('localtax1_type')) {
continue;
Expand Down Expand Up @@ -928,6 +936,9 @@
if ((GETPOST("localtax2_type") || (GETPOST('localtax2_type') == '0')) && !GETPOST("localtax2")) {
$_POST["localtax2"] = '0'; // If empty, we force to 0
}
if (GETPOST('department_buyer_id') <= 0) {
$_POST['department_buyer_id'] = ''; // If empty, we force to null
}
if (GETPOST("accountancy_code") <= 0) {
$_POST["accountancy_code"] = ''; // If empty, we force to null
}
Expand Down Expand Up @@ -1576,6 +1587,9 @@
} // For region page, we do not show the country input
$valuetoshow = $langs->trans("Country");
}
if ($value == 'department_buyer') {
$valuetoshow = '';
}
if ($value == 'recuperableonly') {
$valuetoshow = $langs->trans("NPR");
$class = "center";
Expand All @@ -1601,7 +1615,7 @@
if ($value == 'unit' || $value == 'metric') {
$valuetoshow = $langs->trans("MeasuringUnit");
}
if ($value == 'region_id' || $value == 'country_id') {
if ($value == 'region_id' || $value == 'country_id' || $value == 'department_buyer_id') {
$valuetoshow = '';
}
if ($value == 'accountancy_code') {
Expand Down Expand Up @@ -1821,7 +1835,7 @@
}

$showfield = 1; // By default
if ($value == 'region_id' || $value == 'country_id') {
if ($value == 'region_id' || $value == 'country_id' || $value == 'department_buyer_id') {
$showfield = 0;
}

Expand Down Expand Up @@ -1860,7 +1874,7 @@
}

$showfield = 1; // By default
if ($value == 'region_id' || $value == 'country_id') {
if ($value == 'region_id' || $value == 'country_id' || $value == 'department_buyer_id') {
$showfield = 0;
}

Expand Down Expand Up @@ -2013,6 +2027,9 @@
if ($value == 'country') {
$valuetoshow = $langs->trans("Country");
}
if ($value == 'department_buyer') {
$valuetoshow = $langs->trans('DepartmentBuyer');
}
if ($value == 'recuperableonly') {
$valuetoshow = $langs->trans("NPR");
$cssprefix = "center ";
Expand Down Expand Up @@ -2153,7 +2170,7 @@
$valuetoshow = $langs->trans('Unit');
}

if ($value == 'region_id' || $value == 'country_id') {
if ($value == 'region_id' || $value == 'country_id' || $value == 'department_buyer_id') {
$showfield = 0;
}

Expand Down Expand Up @@ -2428,7 +2445,7 @@
$langs->load('trips');
$key = $langs->trans(strtoupper($obj->code));
$valuetoshow = ($obj->code && $key != strtoupper($obj->code) ? $key : $obj->$value);
} elseif ($value == 'region_id' || $value == 'country_id') {
} elseif ($value == 'region_id' || $value == 'country_id' || $value == 'department_buyer_id') {
$showfield = 0;
} elseif ($value == 'unicode') {
$valuetoshow = $langs->getCurrencySymbol($obj->code, 1);
Expand Down Expand Up @@ -2474,6 +2491,9 @@
}
$valuetoshow = length_accountg($valuetoshow);
} elseif ($value == 'fk_tva') {
if (empty($form->cache_vatrates)) {
$form->load_tva('cache_fk_tva', '', $mysoc, new Societe($db), 0, 0, '', false, -1);
}
foreach ($form->cache_vatrates as $key => $Tab) {
if ($form->cache_vatrates[$key]['rowid'] == $valuetoshow) {
$valuetoshow = $form->cache_vatrates[$key]['label'];
Expand Down Expand Up @@ -2747,6 +2767,25 @@ function dictFieldList($fieldlist, $obj = null, $tabname = '', $context = '')
print '<td>';
print '<input type="hidden" name="'. $value .'" value="'.$region_id.'">';
print '</td>';
} elseif ($value == 'department_buyer') {
if ($context == 'edit') {
print '<td>';
// show department buyer list
$country_code = (!empty($obj->country_code) ? $obj->country_code : '');
$department_buyer_id = (!empty($obj->department_buyer_id) ? (int) $obj->department_buyer_id : 0);
if ($country_code != '') {
print img_picto('', 'state', 'class="pictofixedwidth"');
print $formcompany->select_state($department_buyer_id, $country_code, 'department_buyer_id', 'minwidth100 maxwidth150 maxwidthonsmartphone');
}
print '</td>';
}
} elseif ($value == 'department_buyer_id') {
if (!in_array('department_buyer', $fieldlist)) { // If there is already a field department buyer, we don't show department buyer id (avoid duplicate)
$department_buyer_id = (!empty($obj->{$value}) ? $obj->{$value} : 0);
print '<td class="tdoverflowmax100">';
print '<input type="hidden" name="'.$value.'" value="'.$department_buyer_id.'">';
print '</td>';
}
} elseif ($value == 'lang') {
print '<td>';
print $formadmin->select_language(getDolGlobalString('MAIN_LANG_DEFAULT'), 'lang');
Expand Down
43 changes: 31 additions & 12 deletions htdocs/core/lib/functions.lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -7546,11 +7546,12 @@ function get_product_localtax_for_country($idprod, $local, $thirdpartytouse)
/**
* Function that return vat rate of a product line (according to seller, buyer and product vat rate)
* VATRULE 1: If seller does not use VAT, default VAT is 0. End of rule.
* VATRULE 2: If the (seller country = buyer country) then the default VAT = VAT of the product sold. End of rule.
* VATRULE 3: If (seller and buyer in the European Community) and (property sold = new means of transport such as car, boat, plane) then VAT by default = 0 (VAT must be paid by the buyer to the tax center of his country and not to the seller). End of rule.
* VATRULE 4: If (seller and buyer in the European Community) and (buyer = individual) then VAT by default = VAT of the product sold. End of rule
* VATRULE 5: If (seller and buyer in European Community) and (buyer = company) then VAT by default=0. End of rule
* VATRULE 6: Otherwise the VAT proposed by default=0. End of rule.
* VATRULE 2: If buyer department has a VAT rule from vat rates dictionary then it's the default VAT rate. End of rule.
* VATRULE 3: If the (seller country = buyer country) then the default VAT = VAT of the product sold. End of rule.
* VATRULE 4: If (seller and buyer in the European Community) and (property sold = new means of transport such as car, boat, plane) then VAT by default = 0 (VAT must be paid by the buyer to the tax center of his country and not to the seller). End of rule.
* VATRULE 5: If (seller and buyer in the European Community) and (buyer = individual) then VAT by default = VAT of the product sold. End of rule
* VATRULE 6: If (seller and buyer in European Community) and (buyer = company) then VAT by default=0. End of rule
* VATRULE 7: Otherwise the VAT proposed by default=0. End of rule.
*
* @param Societe $thirdparty_seller Object Seller company
* @param Societe $thirdparty_buyer Object Buyer company
Expand All @@ -7561,7 +7562,7 @@ function get_product_localtax_for_country($idprod, $local, $thirdpartytouse)
*/
function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod = 0, $idprodfournprice = 0)
{
global $conf;
global $conf, $db;

require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';

Expand Down Expand Up @@ -7601,17 +7602,35 @@ function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer,
return 0;
}

// 'VATRULE 2' - Force VAT if a buyer department is defined on vat rates dictionary
if (!empty($thirdparty_buyer->state_id)) {
$sql = "SELECT d.rowid, t.taux as vat_default_rate, t.code as vat_default_code ";
$sql .= " FROM ".$db->prefix()."c_tva as t";
$sql .= " INNER JOIN ".$db->prefix()."c_departements as d ON t.fk_department_buyer = d.rowid";
$sql .= " WHERE d.rowid = ".((int) $thirdparty_buyer->state_id);
$sql .= " ORDER BY t.use_default DESC, t.taux DESC, t.code ASC, t.recuperableonly ASC";

$res = $db->query($sql);
if ($res) {
if ($db->num_rows($res)) {
$obj = $db->fetch_object($res);
return $obj->vat_default_rate.' ('.$obj->vat_default_code.')';
}
$db->free($res);
}
}

// If the (seller country = buyer country) then the default VAT = VAT of the product sold. End of rule.
if (($seller_country_code == $buyer_country_code)
|| (in_array($seller_country_code, array('FR', 'MC')) && in_array($buyer_country_code, array('FR', 'MC')))
|| (in_array($seller_country_code, array('MQ', 'GP')) && in_array($buyer_country_code, array('MQ', 'GP')))
) { // Warning ->country_code not always defined
//print 'VATRULE 2';
//print 'VATRULE 3';
$tmpvat = get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice);

if ($seller_country_code == 'IN' && getDolGlobalString('MAIN_SALETAX_AUTOSWITCH_I_CS_FOR_INDIA')) {
// Special case for india.
//print 'VATRULE 2b';
//print 'VATRULE 3b';
$reg = array();
if (preg_match('/C+S-(\d+)/', $tmpvat, $reg) && $thirdparty_seller->state_id != $thirdparty_buyer->state_id) {
// we must revert the C+S into I
Expand All @@ -7626,7 +7645,7 @@ function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer,
}

// If (seller and buyer in the European Community) and (property sold = new means of transport such as car, boat, plane) then VAT by default = 0 (VAT must be paid by the buyer to the tax center of his country and not to the seller). End of rule.
// 'VATRULE 3' - Not supported
// 'VATRULE 4' - Not supported

// If (seller and buyer in the European Community) and (buyer = individual) then VAT by default = VAT of the product sold. End of rule
// If (seller and buyer in European Community) and (buyer = company) then VAT by default=0. End of rule
Expand All @@ -7640,10 +7659,10 @@ function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer,
}

if (!$isacompany) {
//print 'VATRULE 4';
//print 'VATRULE 5';
return get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice);
} else {
//print 'VATRULE 5';
//print 'VATRULE 6';
return 0;
}
}
Expand All @@ -7660,7 +7679,7 @@ function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer,

// Otherwise the VAT proposed by default=0. End of rule.
// Rem: This means that at least one of the 2 is outside the European Community and the country differs
//print 'VATRULE 6';
//print 'VATRULE 7';
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion htdocs/langs/en_US/admin.lang
Original file line number Diff line number Diff line change
Expand Up @@ -1136,7 +1136,7 @@ BackToDictionaryList=Back to Dictionaries list
TypeOfRevenueStamp=Type of tax stamp
VATManagement=Sales Tax Management
VATIsUsedStandard=When creating documents (proposals, invoices, orders...), the default Sales Tax rate is set according to the standard rules (depending on seller and buyer countries)
VATIsUsedDesc=By default when creating proposals, invoices, orders etc. the Sales Tax rate follows the active standard rule:<br>If the seller is not subject to Sales tax, then Sales tax defaults to 0. End of rule.<br>If the (seller's country = buyer's country), then the Sales tax by default equals the Sales tax of the product in the seller's country. End of rule.<br>If the seller and buyer are both in the European Community and goods are transport-related products (haulage, shipping, airline), the default VAT is 0. This rule is dependent on the seller's country - please consult with your accountant. The VAT should be paid by the buyer to the customs office in their country and not to the seller. End of rule.<br>If the seller and buyer are both in the European Community and the buyer is not a company (with a registered intra-Community VAT number) then the VAT defaults to the VAT rate of the seller's country. End of rule.<br>If the seller and buyer are both in the European Community and the buyer is a company (with a registered intra-Community VAT number), then the VAT is 0 by default. End of rule.<br>In any other case the proposed default is Sales tax=0. End of rule.
VATIsUsedDesc=By default when creating proposals, invoices, orders etc. the Sales Tax rate follows the active standard rule:<br>If the seller is not subject to Sales tax, then Sales tax defaults to 0. End of rule.<br>If buyer department has a VAT rule from vat rates dictionary then it's the default VAT rate. End of rule.<br>If the (seller's country = buyer's country), then the Sales tax by default equals the Sales tax of the product in the seller's country. End of rule.<br>If the seller and buyer are both in the European Community and goods are transport-related products (haulage, shipping, airline), the default VAT is 0. This rule is dependent on the seller's country - please consult with your accountant. The VAT should be paid by the buyer to the customs office in their country and not to the seller. End of rule.<br>If the seller and buyer are both in the European Community and the buyer is not a company (with a registered intra-Community VAT number) then the VAT defaults to the VAT rate of the seller's country. End of rule.<br>If the seller and buyer are both in the European Community and the buyer is a company (with a registered intra-Community VAT number), then the VAT is 0 by default. End of rule.<br>In any other case the proposed default is Sales tax=0. End of rule.
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.
Expand Down
Loading
Loading