Open Daviid-P opened 1 year ago
Hi David, You answer yourself in your approach:
"Only freelancers that carry out professional activities (doctors, lawyers, teachers, translators etc.) must issue their invoices with income tax retention and only if their clients are other freelancers or businesses in Spain"
Only if their clients are other freelancers or businesses. Therefore, you must indicate whether or not your client is subject to IRPF.
In the Third card you can set if the client is subject and the value, since even the type of client can change the rate to be applied (services, leases, etc.)
Hi David, You answer yourself in your approach:
"Only freelancers that carry out professional activities (doctors, lawyers, teachers, translators etc.) must issue their invoices with income tax retention and only if their clients are other freelancers or businesses in Spain"
Only if their clients are other freelancers or businesses. Therefore, you must indicate whether or not your client is subject to IRPF.
In the Third card you can set if the client is subject and the value, since even the type of client can change the rate to be applied (services, leases, etc.)
Isn't "Subject to Local Tax 2" for providers only?
It is for both suppliers and customers
I have a Freelancer that is subject to IRPF so he goes to htdocs/admin/company.php
and sets "Gestión de IRPF" to "Sujeto a IRPF" and selects a default value of -15.
If that freelancer tries to create an invoice of 100€ to Company A (Seller freelancer and Client Company A) which does not apply IRPF when they are providers then FC will be 100 base amount, 21 IVA and 0 IRPF.
If I set in the thirdparty for Company A that they're subject to IRPF then get the -15 of IRPF but I can't create invoices with that thirdparty as a provider because it'll apply IRPF then too.
What's the point of the main configuration if I still have to add the localtax2 to each thirdparty.
Is there any case where I'm the seller and the IRPF set in htdocs/admin/company.php
is different from the IRPF that I should apply to a client? (Needing then to set a IRPF in the thirdparty card)
If not, then the IRPF set in a thirdparty card should only apply for when that thirdparty is a provider, no? I've noticed that, if I set up a thirdparty subject to IRPF I only see that info in the provider tab of the thirdparty card which I think makes it seems as if it only applies to providers.
@simnandez
I think I'm confused, I can't turn off the localtax2 on the main configuration because on htdocs\societe\card.php
it checks if $mysoc->localtax1_assuj == "1" && $mysoc->localtax2_assuj == "1"
before it shows the inputs for localtaxes on the thirdparty.
This doesn't work if my company is not subject to IRPF but we have a provider that is, right?
Am I wrong or is this an actual bug?
@Daviid-P i try to see how to close this ticket. Do you still have trouble. There is still a lot of things i don't understand myself on IRPF. Even if IRPF is not applied by default when you add a product, are you able to apply it after when you edit the line in the order or invoice by selecting another VAT rate with IRPF defined on this VAT rate ?
I don't remember well but I got this working good enough for my company, at least.
Here's how it's on develop branch right now
/**
* Return localtax rate for a particular vat, when selling a product with vat $vatrate, from a $thirdparty_buyer to a $thirdparty_seller
* Note: This function applies same rules than get_default_tva
*
* @param float $vatrate Vat rate. Can be '8.5' or '8.5 (VATCODEX)' for example
* @param int $local Local tax to search and return (1 or 2 return only tax rate 1 or tax rate 2)
* @param Societe $thirdparty_buyer Object of buying third party
* @param Societe $thirdparty_seller Object of selling third party ($mysoc if not defined)
* @param int $vatnpr If vat rate is NPR or not
* @return mixed 0 if not found, localtax rate if found
* @see get_default_tva()
*/
function get_localtax($vatrate, $local, $thirdparty_buyer = "", $thirdparty_seller = "", $vatnpr = 0)
{
global $db, $conf, $mysoc;
if (empty($thirdparty_seller) || !is_object($thirdparty_seller)) {
$thirdparty_seller = $mysoc;
}
dol_syslog("get_localtax tva=" . $vatrate . " local=" . $local . " thirdparty_buyer id=" . (is_object($thirdparty_buyer) ? $thirdparty_buyer->id : '') . "/country_code=" . (is_object($thirdparty_buyer) ? $thirdparty_buyer->country_code : '') . " thirdparty_seller id=" . $thirdparty_seller->id . "/country_code=" . $thirdparty_seller->country_code . " thirdparty_seller localtax1_assuj=" . $thirdparty_seller->localtax1_assuj . " thirdparty_seller localtax2_assuj=" . $thirdparty_seller->localtax2_assuj);
$vatratecleaned = $vatrate;
$reg = array();
if (preg_match('/^(.*)\s*\((.*)\)$/', $vatrate, $reg)) { // If vat is "xx (yy)"
$vatratecleaned = trim($reg[1]);
$vatratecode = $reg[2];
}
/*if ($thirdparty_buyer->country_code != $thirdparty_seller->country_code)
{
return 0;
}*/
// Some test to guess with no need to make database access
if ($mysoc->country_code == 'ES') { // For spain localtaxes 1 and 2, tax is qualified if buyer use local tax
if ($local == 1) {
if (!$mysoc->localtax1_assuj || (string) $vatratecleaned == "0") {
return 0;
}
if ($thirdparty_seller->id == $mysoc->id) {
if (!$thirdparty_buyer->localtax1_assuj) {
return 0;
}
} else {
if (!$thirdparty_seller->localtax1_assuj) {
return 0;
}
}
}
if ($local == 2) {
//if (! $mysoc->localtax2_assuj || (string) $vatratecleaned == "0") return 0;
if (!$mysoc->localtax2_assuj) {
return 0; // If main vat is 0, IRPF may be different than 0.
}
if ($thirdparty_seller->id == $mysoc->id) {
if (!$thirdparty_buyer->localtax2_assuj) {
return 0;
}
} else {
if (!$thirdparty_seller->localtax2_assuj) {
return 0;
}
}
}
} else {
if ($local == 1 && !$thirdparty_seller->localtax1_assuj) {
return 0;
}
if ($local == 2 && !$thirdparty_seller->localtax2_assuj) {
return 0;
}
}
// For some country MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY is forced to on.
if (in_array($mysoc->country_code, array('ES'))) {
$conf->global->MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY = 1;
}
// Search local taxes
if (getDolGlobalString('MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY')) {
if ($local == 1) {
if ($thirdparty_seller != $mysoc) {
if (!isOnlyOneLocalTax($local)) { // TODO We should provide $vatrate to search on correct line and not always on line with highest vat rate
return $thirdparty_seller->localtax1_value;
}
} else { // i am the seller
if (!isOnlyOneLocalTax($local)) { // TODO If seller is me, why not always returning this, even if there is only one locatax vat.
return $conf->global->MAIN_INFO_VALUE_LOCALTAX1;
}
}
}
if ($local == 2) {
if ($thirdparty_seller != $mysoc) {
if (!isOnlyOneLocalTax($local)) { // TODO We should provide $vatrate to search on correct line and not always on line with highest vat rate
// TODO We should also return value defined on thirdparty only if defined
return $thirdparty_seller->localtax2_value;
}
} else { // i am the seller
if (in_array($mysoc->country_code, array('ES'))) {
return $thirdparty_buyer->localtax2_value;
} else {
return $conf->global->MAIN_INFO_VALUE_LOCALTAX2;
}
}
}
}
// By default, search value of local tax on line of common tax
$sql = "SELECT 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($thirdparty_seller->country_code) . "'";
$sql .= " AND t.taux = " . ((float) $vatratecleaned) . " AND t.active = 1";
$sql .= " AND t.entity IN (" . getEntity('c_tva') . ")";
if (!empty($vatratecode)) {
$sql .= " AND t.code ='" . $db->escape($vatratecode) . "'"; // If we have the code, we use it in priority
} else {
$sql .= " AND t.recuperableonly = '" . $db->escape($vatnpr) . "'";
}
$resql = $db->query($sql);
if ($resql) {
$obj = $db->fetch_object($resql);
if ($obj) {
if ($local == 1) {
return $obj->localtax1;
} elseif ($local == 2) {
return $obj->localtax2;
}
}
}
return 0;
}
and here's what I have in my dolibarr
/**
* Return localtax rate for a particular vat, when selling a product with vat $vatrate, from a $thirdparty_buyer to a $thirdparty_seller
* Note: This function applies same rules than get_default_tva
*
* @param float $vatrate Vat rate. Can be '8.5' or '8.5 (VATCODEX)' for example
* @param int $local Local tax to search and return (1 or 2 return only tax rate 1 or tax rate 2)
* @param Societe $thirdparty_buyer Object of buying third party
* @param Societe $thirdparty_seller Object of selling third party ($mysoc if not defined)
* @param int $vatnpr If vat rate is NPR or not
* @return mixed 0 if not found, localtax rate if found
* @see get_default_tva()
*/
function get_localtax($vatrate, $local, $thirdparty_buyer = "", $thirdparty_seller = "", $vatnpr = 0)
{
global $db, $conf, $mysoc;
if (empty($thirdparty_seller) || !is_object($thirdparty_seller)) {
$thirdparty_seller = $mysoc;
}
dol_syslog("get_localtax tva=" . $vatrate . " local=" . $local . " thirdparty_buyer id=" . (is_object($thirdparty_buyer) ? $thirdparty_buyer->id : '') . "/country_code=" . (is_object($thirdparty_buyer) ? $thirdparty_buyer->country_code : '') . " thirdparty_seller id=" . $thirdparty_seller->id . "/country_code=" . $thirdparty_seller->country_code . " thirdparty_seller localtax1_assuj=" . $thirdparty_seller->localtax1_assuj . " thirdparty_seller localtax2_assuj=" . $thirdparty_seller->localtax2_assuj);
$vatratecleaned = $vatrate;
$reg = array();
if (preg_match('/^(.*)\s*\((.*)\)$/', $vatrate, $reg)) { // If vat is "xx (yy)"
$vatratecleaned = trim($reg[1]);
$vatratecode = $reg[2];
}
/*if ($thirdparty_buyer->country_code != $thirdparty_seller->country_code)
{
return 0;
}*/
// Some test to guess with no need to make database access
if ($mysoc->country_code == 'ES') { // For spain localtaxes 1 and 2, tax is qualified if buyer use local tax
if ($local == 1) {
if (!$mysoc->localtax1_assuj || (string) $vatratecleaned == "0") {
return 0;
}
if ($thirdparty_seller->id == $mysoc->id) {
if (!$thirdparty_buyer->localtax1_assuj) {
return 0;
}
} else {
if (!$thirdparty_seller->localtax1_assuj) {
return 0;
}
}
}
if ($local == 2) {
//if (! $mysoc->localtax2_assuj || (string) $vatratecleaned == "0") return 0;
//if (!$mysoc->localtax2_assuj) {
// return 0; // If main vat is 0, IRPF may be different than 0.
//}
if ($thirdparty_seller->id == $mysoc->id) {
// if (!$thirdparty_buyer->localtax2_assuj) {
// return 0;
// }
// evCustom
if (
$conf->global->FACTURE_LOCAL_TAX2_OPTION != "localtax2off" &&
isset($conf->global->MAIN_INFO_VALUE_LOCALTAX2)
) {
return $conf->global->MAIN_INFO_VALUE_LOCALTAX2;
} elseif ($thirdparty_seller->localtax2_assuj) {
return $thirdparty_seller->localtax2_value;
}
// evCustom
} else {
if (!$thirdparty_seller->localtax2_assuj) {
return 0;
}
}
}
} else {
if ($local == 1 && !$thirdparty_seller->localtax1_assuj) {
return 0;
}
if ($local == 2 && !$thirdparty_seller->localtax2_assuj) {
return 0;
}
}
// For some country MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY is forced to on.
if (in_array($mysoc->country_code, array('ES'))) {
$conf->global->MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY = 1;
}
// Search local taxes
if (!empty($conf->global->MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY)) {
if ($local == 1) {
if ($thirdparty_seller != $mysoc) {
if (!isOnlyOneLocalTax($local)) { // TODO We should provide $vatrate to search on correct line and not always on line with highest vat rate
return $thirdparty_seller->localtax1_value;
}
} else { // i am the seller
if (!isOnlyOneLocalTax($local)) { // TODO If seller is me, why not always returning this, even if there is only one locatax vat.
return $conf->global->MAIN_INFO_VALUE_LOCALTAX1;
}
}
}
if ($local == 2) {
if ($thirdparty_seller != $mysoc) {
if (!isOnlyOneLocalTax($local)) { // TODO We should provide $vatrate to search on correct line and not always on line with highest vat rate
// TODO We should also return value defined on thirdparty only if defined
return $thirdparty_seller->localtax2_value;
}
} else { // i am the seller
// evCustom
if (
$conf->global->FACTURE_LOCAL_TAX2_OPTION != "localtax2off" &&
isset($conf->global->MAIN_INFO_VALUE_LOCALTAX2)
) {
return $conf->global->MAIN_INFO_VALUE_LOCALTAX2;
} elseif ($thirdparty_buyer->localtax2_value > 0) {
return $thirdparty_buyer->localtax2_value;
}
// evCustom
//if (in_array($mysoc->country_code, array('ES'))) {
// return $thirdparty_buyer->localtax2_value;
//} else {
// return $conf->global->MAIN_INFO_VALUE_LOCALTAX2;
//}
}
}
}
// By default, search value of local tax on line of common tax
$sql = "SELECT 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($thirdparty_seller->country_code) . "'";
$sql .= " AND t.taux = " . ((float) $vatratecleaned) . " AND t.active = 1";
if (!empty($vatratecode)) {
$sql .= " AND t.code ='" . $db->escape($vatratecode) . "'"; // If we have the code, we use it in priority
} else {
$sql .= " AND t.recuperableonly = '" . $db->escape($vatnpr) . "'";
}
$resql = $db->query($sql);
if ($resql) {
$obj = $db->fetch_object($resql);
if ($obj) {
if ($local == 1) {
return $obj->localtax1;
} elseif ($local == 2) {
return $obj->localtax2;
}
}
}
return 0;
}
Images of the changes:
Like this I don't need to add localtax to the products, I just select TVA when adding the Invoice Line
Third party must be set to locatax2_assuj and the correct tax must be selected.
I don't dare touch it anymore as long as it's working for us.
TL;DR You can close this without any trouble. I don't remember why I changed what I changed.
This bug is still present in version 18
Daviid-P said:
Is there any case where I'm the seller and the IRPF set in
htdocs/admin/company.php
is different from the IRPF that I should apply to a client? (Needing then to set a IRPF in the thirdparty card)If not, then the IRPF set in a thirdparty card should only apply for when that thirdparty is a provider, no? I've noticed that, if I set up a thirdparty subject to IRPF I only see that info in the provider tab of the thirdparty card which I think makes it seems as if it only applies to providers.
First answer is NOT, but you need to know if must apply it (only companies, not individual customers). We'll use $conf->global->MAIN_INFO_VALUE_LOCALTAX2 and should be mandatory.
So second answer is YES. Only sellers set type of IRPF.
I think code is wrong, the spanish exception should be the other way around, buyer don't set IRPF.
if (in_array($mysoc->country_code, array('ES'))) {
return $thirdparty_buyer->localtax2_value;
} else {
return $conf->global->MAIN_INFO_VALUE_LOCALTAX2;
}
And finaly, code show localtax2 in products, but that doesn't make sense if localtax2 is IRPF. It is unique for freelancers (IRPF means Impuesto sobre la Renta de las Personas Físicas = personal income tax).
Sorry, I don't know if the topic is related.
Normally, I can make invoices with the -15% IRPF tax.
But this does not happen when lines are added from project task times.
Editing the lines of the draft invoice does not add the -15% IRPF tax either.
My company has marked the use of -15% IRPF Tax and the client has also indicated it. If I make a normal invoice everything is correct, but not the time spent invoiced on a project task. Nor if I select a service for that time dedicated to billing.
Bug
I have configured in
admin/company.php
that localtax2on is true (Sujeto a IRPF) and the value is set (-15)But when I create an invoice for a client I don't get any IRPF added.
As far as I can see, when adding tax to a service I get
21/0/0%
, those zeros come fromproduct/price.php
because for some reason there's this comment:Then in
get_localtax()
there's this:I'm creating a client invoice, so my company is the $thirdparty_seller. Then it checks if the $thirdparty_buyer is subject to localtax2.
From this page:
I thought that the configuration in
admin/company.php
was something "global" as in, if localtax2 is on then all invoices to clients have localtax2 by default.Am I misunderstanding something here??
Environment Version
No response
Environment OS
No response
Environment Web server
No response
Environment PHP
No response
Environment Database
No response
Environment URL(s)
No response
Expected and actual behavior
If local tax 2 is enabled in
admin/company.php
add local tax 2 by default to client invoices except when explicitly set to otherwise in the thirdparty card in client tab.If local tax 2 is enabled in
admin/company.php
change all thirdparty clients to subject to localtax2 (by default, with a checkbox or with a confirmation form)Steps to reproduce the behavior
No response
Attached files
No response