mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-07 12:34:30 -04:00
Add US states / zip codes
This commit is contained in:
parent
d687d364d8
commit
699c3cdd9b
@ -27,6 +27,12 @@ class BaseRule implements RuleInterface
|
|||||||
|
|
||||||
public bool $foreign_consumer_tax_exempt = true;
|
public bool $foreign_consumer_tax_exempt = true;
|
||||||
|
|
||||||
|
public string $vendor_iso_3166_2 = '';
|
||||||
|
|
||||||
|
public string $client_iso_3166_2 = '';
|
||||||
|
|
||||||
|
public string $client_region = '';
|
||||||
|
|
||||||
public array $eu_country_codes = [
|
public array $eu_country_codes = [
|
||||||
'AT', // Austria
|
'AT', // Austria
|
||||||
'BE', // Belgium
|
'BE', // Belgium
|
||||||
@ -57,6 +63,38 @@ class BaseRule implements RuleInterface
|
|||||||
'SK', // Slovakia
|
'SK', // Slovakia
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public array $region_codes = [
|
||||||
|
'AT' => 'EU', // Austria
|
||||||
|
'BE' => 'EU', // Belgium
|
||||||
|
'BG' => 'EU', // Bulgaria
|
||||||
|
'CY' => 'EU', // Cyprus
|
||||||
|
'CZ' => 'EU', // Czech Republic
|
||||||
|
'DE' => 'EU', // Germany
|
||||||
|
'DK' => 'EU', // Denmark
|
||||||
|
'EE' => 'EU', // Estonia
|
||||||
|
'ES' => 'EU', // Spain
|
||||||
|
'FI' => 'EU', // Finland
|
||||||
|
'FR' => 'EU', // France
|
||||||
|
'GR' => 'EU', // Greece
|
||||||
|
'HR' => 'EU', // Croatia
|
||||||
|
'HU' => 'EU', // Hungary
|
||||||
|
'IE' => 'EU', // Ireland
|
||||||
|
'IT' => 'EU', // Italy
|
||||||
|
'LT' => 'EU', // Lithuania
|
||||||
|
'LU' => 'EU', // Luxembourg
|
||||||
|
'LV' => 'EU', // Latvia
|
||||||
|
'MT' => 'EU', // Malta
|
||||||
|
'NL' => 'EU', // Netherlands
|
||||||
|
'PL' => 'EU', // Poland
|
||||||
|
'PT' => 'EU', // Portugal
|
||||||
|
'RO' => 'EU', // Romania
|
||||||
|
'SE' => 'EU', // Sweden
|
||||||
|
'SI' => 'EU', // Slovenia
|
||||||
|
'SK' => 'EU', // Slovakia
|
||||||
|
|
||||||
|
'US' => 'US', // United States
|
||||||
|
];
|
||||||
|
|
||||||
/** EU TAXES */
|
/** EU TAXES */
|
||||||
|
|
||||||
|
|
||||||
@ -89,6 +127,21 @@ class BaseRule implements RuleInterface
|
|||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
|
|
||||||
|
$this->resolveRegions();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveRegions(): self
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!array_key_exists($this->client->country->iso_3166_2, $this->region_codes))
|
||||||
|
throw new \Exception('Country not supported');
|
||||||
|
|
||||||
|
$this->client_region = $this->region_codes[$this->client->country->iso_3166_2] ?? '';
|
||||||
|
|
||||||
|
$this->client_subregion =
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,16 +13,15 @@ namespace App\DataMapper\Tax\DE;
|
|||||||
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use App\DataMapper\Tax\BaseRule;
|
use App\DataMapper\Tax\BaseRule;
|
||||||
use App\DataMapper\Tax\RuleInterface;
|
use App\DataMapper\Tax\RuleInterface;
|
||||||
use App\DataMapper\Tax\ZipTax\Response;
|
use App\DataMapper\Tax\ZipTax\Response;
|
||||||
|
|
||||||
class Rule extends BaseRule implements RuleInterface
|
class Rule extends BaseRule implements RuleInterface
|
||||||
{
|
{
|
||||||
public string $vendor_country_code = 'DE';
|
public string $vendor_iso_3166_2 = 'DE';
|
||||||
|
|
||||||
public string $client_country_code = 'DE';
|
public string $client_iso_3166_2 = 'DE';
|
||||||
|
|
||||||
public bool $consumer_tax_exempt = false;
|
public bool $consumer_tax_exempt = false;
|
||||||
|
|
||||||
@ -34,33 +33,13 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
|
|
||||||
public bool $foreign_consumer_tax_exempt = true;
|
public bool $foreign_consumer_tax_exempt = true;
|
||||||
|
|
||||||
public string $tax_name1 = '';
|
|
||||||
|
|
||||||
public float $tax_rate1 = 0;
|
|
||||||
|
|
||||||
public string $tax_name2 = '';
|
|
||||||
|
|
||||||
public float $tax_rate2 = 0;
|
|
||||||
|
|
||||||
public string $tax_name3 = '';
|
|
||||||
|
|
||||||
public float $tax_rate3 = 0;
|
|
||||||
|
|
||||||
public float $vat_rate = 0;
|
public float $vat_rate = 0;
|
||||||
|
|
||||||
public float $reduced_vat_rate = 0;
|
public float $reduced_vat_rate = 0;
|
||||||
|
|
||||||
protected ?Client $client;
|
|
||||||
|
|
||||||
protected ?Response $tax_data;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function init(): self
|
public function init(): self
|
||||||
{
|
{
|
||||||
$this->client_country_code = $this->client->shipping_country ? $this->client->shipping_country->iso_3166_2 : $this->client->country->iso_3166_2;
|
$this->client_iso_3166_2 = $this->client->shipping_country ? $this->client->shipping_country->iso_3166_2 : $this->client->country->iso_3166_2;
|
||||||
$this->calculateRates();
|
$this->calculateRates();
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -89,7 +68,7 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
|
|
||||||
return $this->taxExempt();
|
return $this->taxExempt();
|
||||||
|
|
||||||
} elseif ($this->client->company->tax_data->regions->EU->tax_all_subregions || $this->client->company->tax_data->regions->EU->subregions->{$this->client_country_code}->apply_tax) {
|
} elseif ($this->client->company->tax_data->regions->EU->tax_all_subregions || $this->client->company->tax_data->regions->EU->subregions->{$this->client_iso_3166_2}->apply_tax) {
|
||||||
|
|
||||||
$this->taxByType($type);
|
$this->taxByType($type);
|
||||||
|
|
||||||
@ -190,21 +169,21 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
$this->vat_rate = 0;
|
$this->vat_rate = 0;
|
||||||
$this->reduced_vat_rate = 0;
|
$this->reduced_vat_rate = 0;
|
||||||
}
|
}
|
||||||
elseif($this->client_country_code != $this->vendor_country_code && in_array($this->client_country_code, $this->eu_country_codes) && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt)
|
elseif($this->client_iso_3166_2 != $this->vendor_iso_3166_2 && in_array($this->client_iso_3166_2, $this->eu_country_codes) && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt)
|
||||||
{
|
{
|
||||||
$this->vat_rate = 0;
|
$this->vat_rate = 0;
|
||||||
$this->reduced_vat_rate = 0;
|
$this->reduced_vat_rate = 0;
|
||||||
// nlog("euro zone and tax exempt");
|
// nlog("euro zone and tax exempt");
|
||||||
}
|
}
|
||||||
elseif(!in_array(strtoupper($this->client_country_code), $this->eu_country_codes) && ($this->foreign_consumer_tax_exempt || $this->foreign_business_tax_exempt)) //foreign + tax exempt
|
elseif(!in_array(strtoupper($this->client_iso_3166_2), $this->eu_country_codes) && ($this->foreign_consumer_tax_exempt || $this->foreign_business_tax_exempt)) //foreign + tax exempt
|
||||||
{
|
{
|
||||||
$this->vat_rate = 0;
|
$this->vat_rate = 0;
|
||||||
$this->reduced_vat_rate = 0;
|
$this->reduced_vat_rate = 0;
|
||||||
// nlog("foreign and tax exempt");
|
// nlog("foreign and tax exempt");
|
||||||
}
|
}
|
||||||
elseif(in_array(strtoupper($this->client_country_code), $this->eu_country_codes) && !$this->client->has_valid_vat_number) //eu country / no valid vat
|
elseif(in_array(strtoupper($this->client_iso_3166_2), $this->eu_country_codes) && !$this->client->has_valid_vat_number) //eu country / no valid vat
|
||||||
{
|
{
|
||||||
if(($this->vendor_country_code != $this->client_country_code) && $this->client->company->tax_data->regions->EU->has_sales_above_threshold)
|
if(($this->vendor_iso_3166_2 != $this->client_iso_3166_2) && $this->client->company->tax_data->regions->EU->has_sales_above_threshold)
|
||||||
{
|
{
|
||||||
$this->vat_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->vat_rate;
|
$this->vat_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->vat_rate;
|
||||||
$this->reduced_vat_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_vat_rate;
|
$this->reduced_vat_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_vat_rate;
|
||||||
|
@ -13,30 +13,14 @@ namespace App\DataMapper\Tax\US;
|
|||||||
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\DataMapper\Tax\BaseRule;
|
||||||
use App\DataMapper\Tax\RuleInterface;
|
use App\DataMapper\Tax\RuleInterface;
|
||||||
use App\DataMapper\Tax\ZipTax\Response;
|
use App\DataMapper\Tax\ZipTax\Response;
|
||||||
|
|
||||||
class Rule implements RuleInterface
|
class Rule extends BaseRule implements RuleInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
public string $tax_name1 = '';
|
public function override(): self
|
||||||
public float $tax_rate1 = 0;
|
|
||||||
|
|
||||||
public string $tax_name2 = '';
|
|
||||||
public float $tax_rate2 = 0;
|
|
||||||
|
|
||||||
public string $tax_name3 = '';
|
|
||||||
public float $tax_rate3 = 0;
|
|
||||||
|
|
||||||
public ?Client $client;
|
|
||||||
|
|
||||||
public ?Response $tax_data;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function override()
|
|
||||||
{
|
{
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -51,6 +35,7 @@ class Rule implements RuleInterface
|
|||||||
public function setClient(Client $client):self
|
public function setClient(Client $client):self
|
||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
|
$this->client_iso_3166_2 = $client->country->iso_3166_2;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -67,7 +52,9 @@ class Rule implements RuleInterface
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
else if($this->client->company->tax_data->regions->{$this->client_region}->tax_all_subregions || $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_iso_3166_2}->apply_tax){ //other regions outside of US
|
||||||
|
|
||||||
|
}
|
||||||
return $this;
|
return $this;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -269,9 +269,9 @@ class EuTaxTest extends TestCase
|
|||||||
$process->setClient($client);
|
$process->setClient($client);
|
||||||
$process->init();
|
$process->init();
|
||||||
|
|
||||||
$this->assertEquals('DE', $process->vendor_country_code);
|
$this->assertEquals('DE', $process->vendor_iso_3166_2);
|
||||||
|
|
||||||
$this->assertEquals('DE', $process->client_country_code);
|
$this->assertEquals('DE', $process->client_iso_3166_2);
|
||||||
|
|
||||||
$this->assertFalse($client->has_valid_vat_number);
|
$this->assertFalse($client->has_valid_vat_number);
|
||||||
|
|
||||||
@ -316,9 +316,9 @@ class EuTaxTest extends TestCase
|
|||||||
$process->init();
|
$process->init();
|
||||||
|
|
||||||
|
|
||||||
$this->assertEquals('DE', $process->vendor_country_code);
|
$this->assertEquals('DE', $process->vendor_iso_3166_2);
|
||||||
|
|
||||||
$this->assertEquals('BE', $process->client_country_code);
|
$this->assertEquals('BE', $process->client_iso_3166_2);
|
||||||
|
|
||||||
$this->assertFalse($client->has_valid_vat_number);
|
$this->assertFalse($client->has_valid_vat_number);
|
||||||
|
|
||||||
@ -354,9 +354,9 @@ class EuTaxTest extends TestCase
|
|||||||
$process->setClient($client);
|
$process->setClient($client);
|
||||||
$process->init();
|
$process->init();
|
||||||
|
|
||||||
$this->assertEquals('DE', $process->vendor_country_code);
|
$this->assertEquals('DE', $process->vendor_iso_3166_2);
|
||||||
|
|
||||||
$this->assertEquals('US', $process->client_country_code);
|
$this->assertEquals('US', $process->client_iso_3166_2);
|
||||||
|
|
||||||
$this->assertFalse($client->has_valid_vat_number);
|
$this->assertFalse($client->has_valid_vat_number);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user