mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Exempt foreign exports
This commit is contained in:
parent
aa156330db
commit
d81029c445
@ -173,6 +173,15 @@ class BaseRule implements RuleInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function defaultForeign(): self
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->tax_rate1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_rate;
|
||||||
|
$this->tax_name1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setTaxData(Response $tax_data): self
|
public function setTaxData(Response $tax_data): self
|
||||||
{
|
{
|
||||||
$this->tax_data = $tax_data;
|
$this->tax_data = $tax_data;
|
||||||
|
@ -17,7 +17,11 @@ use App\Models\Product;
|
|||||||
|
|
||||||
class Rule extends BaseRule implements RuleInterface
|
class Rule extends BaseRule implements RuleInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The rules apply US => US taxes using the tax calculator.
|
||||||
|
*
|
||||||
|
* US => Foreign taxes we check the product types still for exemptions, and we all back to the client country tax rate.
|
||||||
|
*/
|
||||||
public function init(): self
|
public function init(): self
|
||||||
{
|
{
|
||||||
$this->calculateRates();
|
$this->calculateRates();
|
||||||
@ -42,6 +46,13 @@ class Rule extends BaseRule implements RuleInterface
|
|||||||
return $this;
|
return $this;
|
||||||
} elseif($this->isTaxableRegion()) { //other regions outside of US
|
} elseif($this->isTaxableRegion()) { //other regions outside of US
|
||||||
|
|
||||||
|
match($item->tax_id) {
|
||||||
|
Product::PRODUCT_TYPE_EXEMPT => $this->taxExempt(),
|
||||||
|
Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced(),
|
||||||
|
Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override(),
|
||||||
|
default => $this->defaultForeign(),
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ use Tests\TestCase;
|
|||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Product;
|
||||||
use Tests\MockAccountData;
|
use Tests\MockAccountData;
|
||||||
use App\DataMapper\Tax\DE\Rule;
|
use App\DataMapper\Tax\DE\Rule;
|
||||||
use App\DataMapper\Tax\TaxModel;
|
use App\DataMapper\Tax\TaxModel;
|
||||||
@ -145,6 +146,209 @@ class UsTaxTest extends TestCase
|
|||||||
return $invoice;
|
return $invoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testForeignTaxesEnabledWithExemptProduct()
|
||||||
|
{
|
||||||
|
$settings = CompanySettings::defaults();
|
||||||
|
$settings->country_id = '840'; // germany
|
||||||
|
|
||||||
|
$tax_data = new TaxModel();
|
||||||
|
$tax_data->seller_subregion = 'CA';
|
||||||
|
$tax_data->regions->US->has_sales_above_threshold = true;
|
||||||
|
$tax_data->regions->US->tax_all_subregions = true;
|
||||||
|
$tax_data->regions->EU->has_sales_above_threshold = true;
|
||||||
|
$tax_data->regions->EU->tax_all_subregions = true;
|
||||||
|
$tax_data->regions->EU->subregions->DE->tax_rate = 21;
|
||||||
|
|
||||||
|
$company = Company::factory()->create([
|
||||||
|
'account_id' => $this->account->id,
|
||||||
|
'settings' => $settings,
|
||||||
|
'tax_data' => $tax_data,
|
||||||
|
'calculate_taxes' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$client = Client::factory()->create([
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'country_id' => 276,
|
||||||
|
'shipping_country_id' => 276,
|
||||||
|
'has_valid_vat_number' => false,
|
||||||
|
'postal_code' => 'xx',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoice = Invoice::factory()->create([
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'client_id' => $client->id,
|
||||||
|
'status_id' => 1,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'uses_inclusive_taxes' => false,
|
||||||
|
'discount' => 0,
|
||||||
|
'line_items' => [
|
||||||
|
[
|
||||||
|
'product_key' => 'Test',
|
||||||
|
'notes' => 'Test',
|
||||||
|
'cost' => 100,
|
||||||
|
'quantity' => 1,
|
||||||
|
'tax_name1' => '',
|
||||||
|
'tax_rate1' => 0,
|
||||||
|
'tax_name2' => '',
|
||||||
|
'tax_rate2' => 0,
|
||||||
|
'tax_name3' => '',
|
||||||
|
'tax_rate3' => 0,
|
||||||
|
'type_id' => '1',
|
||||||
|
'tax_id' => Product::PRODUCT_TYPE_EXEMPT,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'tax_rate1' => 0,
|
||||||
|
'tax_rate2' => 0,
|
||||||
|
'tax_rate3' => 0,
|
||||||
|
'tax_name1' => '',
|
||||||
|
'tax_name2' => '',
|
||||||
|
'tax_name3' => '',
|
||||||
|
'tax_data' => new Response($this->mock_response),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||||
|
|
||||||
|
$this->assertEquals(100, $invoice->amount);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testForeignTaxesDisabled()
|
||||||
|
{
|
||||||
|
$settings = CompanySettings::defaults();
|
||||||
|
$settings->country_id = '840'; // germany
|
||||||
|
|
||||||
|
$tax_data = new TaxModel();
|
||||||
|
$tax_data->seller_subregion = 'CA';
|
||||||
|
$tax_data->regions->US->has_sales_above_threshold = true;
|
||||||
|
$tax_data->regions->US->tax_all_subregions = true;
|
||||||
|
$tax_data->regions->EU->has_sales_above_threshold = true;
|
||||||
|
$tax_data->regions->EU->tax_all_subregions = false;
|
||||||
|
$tax_data->regions->EU->subregions->DE->tax_rate = 21;
|
||||||
|
|
||||||
|
$company = Company::factory()->create([
|
||||||
|
'account_id' => $this->account->id,
|
||||||
|
'settings' => $settings,
|
||||||
|
'tax_data' => $tax_data,
|
||||||
|
'calculate_taxes' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$client = Client::factory()->create([
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'country_id' => 276,
|
||||||
|
'shipping_country_id' => 276,
|
||||||
|
'has_valid_vat_number' => false,
|
||||||
|
'postal_code' => 'xx',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoice = Invoice::factory()->create([
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'client_id' => $client->id,
|
||||||
|
'status_id' => 1,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'uses_inclusive_taxes' => false,
|
||||||
|
'discount' => 0,
|
||||||
|
'line_items' => [
|
||||||
|
[
|
||||||
|
'product_key' => 'Test',
|
||||||
|
'notes' => 'Test',
|
||||||
|
'cost' => 100,
|
||||||
|
'quantity' => 1,
|
||||||
|
'tax_name1' => '',
|
||||||
|
'tax_rate1' => 0,
|
||||||
|
'tax_name2' => '',
|
||||||
|
'tax_rate2' => 0,
|
||||||
|
'tax_name3' => '',
|
||||||
|
'tax_rate3' => 0,
|
||||||
|
'type_id' => '1',
|
||||||
|
'tax_id' => Product::PRODUCT_TYPE_PHYSICAL,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'tax_rate1' => 0,
|
||||||
|
'tax_rate2' => 0,
|
||||||
|
'tax_rate3' => 0,
|
||||||
|
'tax_name1' => '',
|
||||||
|
'tax_name2' => '',
|
||||||
|
'tax_name3' => '',
|
||||||
|
'tax_data' => new Response($this->mock_response),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||||
|
|
||||||
|
$this->assertEquals(100, $invoice->amount);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testForeignTaxesEnabled()
|
||||||
|
{
|
||||||
|
$settings = CompanySettings::defaults();
|
||||||
|
$settings->country_id = '840'; // germany
|
||||||
|
|
||||||
|
$tax_data = new TaxModel();
|
||||||
|
$tax_data->seller_subregion = 'CA';
|
||||||
|
$tax_data->regions->US->has_sales_above_threshold = true;
|
||||||
|
$tax_data->regions->US->tax_all_subregions = true;
|
||||||
|
$tax_data->regions->EU->has_sales_above_threshold = true;
|
||||||
|
$tax_data->regions->EU->tax_all_subregions = true;
|
||||||
|
$tax_data->regions->EU->subregions->DE->tax_rate = 21;
|
||||||
|
|
||||||
|
$company = Company::factory()->create([
|
||||||
|
'account_id' => $this->account->id,
|
||||||
|
'settings' => $settings,
|
||||||
|
'tax_data' => $tax_data,
|
||||||
|
'calculate_taxes' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$client = Client::factory()->create([
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'country_id' => 276,
|
||||||
|
'shipping_country_id' => 276,
|
||||||
|
'has_valid_vat_number' => false,
|
||||||
|
'postal_code' => 'xx',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoice = Invoice::factory()->create([
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'client_id' => $client->id,
|
||||||
|
'status_id' => 1,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'uses_inclusive_taxes' => false,
|
||||||
|
'discount' => 0,
|
||||||
|
'line_items' => [
|
||||||
|
[
|
||||||
|
'product_key' => 'Test',
|
||||||
|
'notes' => 'Test',
|
||||||
|
'cost' => 100,
|
||||||
|
'quantity' => 1,
|
||||||
|
'tax_name1' => '',
|
||||||
|
'tax_rate1' => 0,
|
||||||
|
'tax_name2' => '',
|
||||||
|
'tax_rate2' => 0,
|
||||||
|
'tax_name3' => '',
|
||||||
|
'tax_rate3' => 0,
|
||||||
|
'type_id' => '1',
|
||||||
|
'tax_id' => Product::PRODUCT_TYPE_PHYSICAL,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'tax_rate1' => 0,
|
||||||
|
'tax_rate2' => 0,
|
||||||
|
'tax_rate3' => 0,
|
||||||
|
'tax_name1' => '',
|
||||||
|
'tax_name2' => '',
|
||||||
|
'tax_name3' => '',
|
||||||
|
'tax_data' => new Response($this->mock_response),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||||
|
|
||||||
|
$this->assertEquals(121, $invoice->amount);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function testCompanyTaxAllOffButTaxUSRegion()
|
public function testCompanyTaxAllOffButTaxUSRegion()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user