mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 13:12:50 +01:00
Refactor for taxes
This commit is contained in:
parent
252effabef
commit
f356ddd845
@ -15,6 +15,7 @@ use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Product;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
use App\DataProviders\USStates;
|
||||
|
||||
class BaseRule implements RuleInterface
|
||||
{
|
||||
@ -116,7 +117,7 @@ class BaseRule implements RuleInterface
|
||||
|
||||
protected ?Client $client;
|
||||
|
||||
protected ?Response $tax_data;
|
||||
public ?Response $tax_data;
|
||||
|
||||
public mixed $invoice;
|
||||
|
||||
@ -129,29 +130,41 @@ class BaseRule implements RuleInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setInvoice(mixed $invoice): self
|
||||
public function setEntity(mixed $invoice): self
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
|
||||
$this->configTaxData();
|
||||
|
||||
$this->client = $invoice->client;
|
||||
|
||||
$this->configTaxData()
|
||||
->resolveRegions();
|
||||
|
||||
$this->tax_data = new Response($this->invoice->tax_data);
|
||||
|
||||
$this->resolveRegions();
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function configTaxData(): self
|
||||
{
|
||||
|
||||
if(!array_key_exists($this->client->country->iso_3166_2, $this->region_codes)) {
|
||||
throw new \Exception('Automatic tax calculations not supported for this country');
|
||||
}
|
||||
|
||||
$this->client_region = $this->region_codes[$this->client->country->iso_3166_2];
|
||||
|
||||
if($this->invoice->tax_data && $this->invoice->status_id > 1)
|
||||
return $this;
|
||||
|
||||
//determine if we are taxing locally or if we are taxing globally
|
||||
// $this->invoice->tax_data = $this->invoice->client->tax_data;
|
||||
$this->invoice->tax_data = $this->invoice->client->tax_data ?: new Response([]);
|
||||
|
||||
if(strlen($this->invoice->tax_data?->originDestination) == 0 && $this->client->company->tax_data->seller_subregion != $this->client_subregion) {
|
||||
$tax_data = $this->invoice->tax_data;
|
||||
$tax_data->originDestination = "D";
|
||||
$this->invoice->tax_data = $tax_data;
|
||||
$this->invoice->saveQuietly();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -160,20 +173,25 @@ class BaseRule implements RuleInterface
|
||||
private function resolveRegions(): self
|
||||
{
|
||||
|
||||
if(!array_key_exists($this->client->country->iso_3166_2, $this->region_codes))
|
||||
throw new \Exception('Automatic tax calculations not supported for this country');
|
||||
|
||||
$this->client_region = $this->region_codes[$this->client->country->iso_3166_2];
|
||||
|
||||
match($this->client_region){
|
||||
'US' => $this->client_subregion = $this->tax_data->geoState,
|
||||
'US' => $this->client_subregion = strlen($this->invoice?->tax_data?->geoState) > 1 ? $this->invoice?->tax_data?->geoState : $this->getUSState(),
|
||||
'EU' => $this->client_subregion = $this->client->country->iso_3166_2,
|
||||
'AU' => $this->client_subregion = 'AU',
|
||||
default => $this->client_subregion = $this->client->country->iso_3166_2,
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function getUSState(): string
|
||||
{
|
||||
try {
|
||||
return USStates::getState(strlen($this->client->postal_code) > 1 ? $this->client->postal_code : $this->client->shipping_postal_code);
|
||||
} catch (\Exception $e) {
|
||||
return 'CA';
|
||||
}
|
||||
}
|
||||
|
||||
public function isTaxableRegion(): bool
|
||||
{
|
||||
return $this->client->company->tax_data->regions->{$this->client_region}->tax_all_subregions || $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->apply_tax;
|
||||
|
@ -148,7 +148,7 @@ class InvoiceItemSum
|
||||
|
||||
$this->rule = new $class();
|
||||
$this->rule
|
||||
->setInvoice($this->invoice)
|
||||
->setEntity($this->invoice)
|
||||
->init();
|
||||
|
||||
$this->calc_tax = true;
|
||||
|
@ -480,14 +480,14 @@ class SchedulerTest extends TestCase
|
||||
$c = Client::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'number' => rand(1000, 100000),
|
||||
'number' => rand(1000, 10000000),
|
||||
'name' => 'A fancy client'
|
||||
]);
|
||||
|
||||
$c2 = Client::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'user_id' => $this->user->id,
|
||||
'number' => rand(1000, 100000),
|
||||
'number' => rand(1000, 10000000),
|
||||
'name' => 'A fancy client'
|
||||
]);
|
||||
|
||||
|
@ -349,7 +349,7 @@ class EuTaxTest extends TestCase
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setInvoice($invoice);
|
||||
$process->setEntity($invoice);
|
||||
$process->init();
|
||||
|
||||
$this->assertEquals('EU', $process->seller_region);
|
||||
@ -403,7 +403,7 @@ class EuTaxTest extends TestCase
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setInvoice($invoice);
|
||||
$process->setEntity($invoice);
|
||||
$process->init();
|
||||
|
||||
$this->assertEquals('EU', $process->seller_region);
|
||||
@ -458,7 +458,7 @@ class EuTaxTest extends TestCase
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setInvoice($invoice);
|
||||
$process->setEntity($invoice);
|
||||
$process->init();
|
||||
|
||||
$this->assertEquals('EU', $process->seller_region);
|
||||
@ -513,7 +513,7 @@ class EuTaxTest extends TestCase
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setInvoice($invoice);
|
||||
$process->setEntity($invoice);
|
||||
$process->init();
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
@ -564,7 +564,7 @@ class EuTaxTest extends TestCase
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setInvoice($invoice);
|
||||
$process->setEntity($invoice);
|
||||
$process->init();
|
||||
|
||||
|
||||
@ -615,7 +615,7 @@ class EuTaxTest extends TestCase
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setInvoice($invoice);
|
||||
$process->setEntity($invoice);
|
||||
$process->init();
|
||||
|
||||
|
||||
@ -666,7 +666,7 @@ class EuTaxTest extends TestCase
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setInvoice($invoice);
|
||||
$process->setEntity($invoice);
|
||||
$process->init();
|
||||
|
||||
|
||||
@ -717,7 +717,7 @@ class EuTaxTest extends TestCase
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setInvoice($invoice);
|
||||
$process->setEntity($invoice);
|
||||
$process->init();
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
@ -766,7 +766,7 @@ class EuTaxTest extends TestCase
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setInvoice($invoice);
|
||||
$process->setEntity($invoice);
|
||||
$process->init();
|
||||
|
||||
|
||||
|
@ -102,10 +102,13 @@ class SumTaxTest extends TestCase
|
||||
$this->company->tax_data = $tax_data;
|
||||
$this->company->save();
|
||||
|
||||
$tax_data = new TaxData($this->response);
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'country_id' => 840,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
$invoice = InvoiceFactory::create($this->company->id, $this->user->id);
|
||||
@ -114,7 +117,7 @@ class SumTaxTest extends TestCase
|
||||
|
||||
$line_items = [];
|
||||
|
||||
$invoice->tax_data = new TaxData($this->response);
|
||||
$invoice->tax_data = $tax_data;
|
||||
|
||||
$line_item = new InvoiceItem();
|
||||
$line_item->quantity = 1;
|
||||
@ -131,7 +134,6 @@ class SumTaxTest extends TestCase
|
||||
|
||||
$line_items = $invoice->line_items;
|
||||
|
||||
|
||||
$this->assertEquals(10, $invoice->amount);
|
||||
$this->assertEquals("", $line_items[0]->tax_name1);
|
||||
$this->assertEquals(0, $line_items[0]->tax_rate1);
|
||||
@ -152,19 +154,23 @@ class SumTaxTest extends TestCase
|
||||
$this->company->tax_data = $tax_data;
|
||||
$this->company->save();
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'country_id' => 840,
|
||||
]);
|
||||
$tax_data = new TaxData($this->response);
|
||||
|
||||
$invoice = InvoiceFactory::create($this->company->id, $this->user->id);
|
||||
$invoice->client_id = $client->id;
|
||||
$invoice->uses_inclusive_taxes = false;
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
'country_id' => 840,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
$line_items = [];
|
||||
$invoice = InvoiceFactory::create($this->company->id, $this->user->id);
|
||||
$invoice->client_id = $client->id;
|
||||
$invoice->uses_inclusive_taxes = false;
|
||||
|
||||
$line_items = [];
|
||||
|
||||
$invoice->tax_data = $tax_data;
|
||||
|
||||
$invoice->tax_data = new TaxData($this->response);
|
||||
|
||||
$line_item = new InvoiceItem;
|
||||
$line_item->quantity = 1;
|
||||
|
@ -107,6 +107,7 @@ class UsTaxTest extends TestCase
|
||||
'shipping_country_id' => 840,
|
||||
'has_valid_vat_number' => false,
|
||||
'postal_code' => $postal_code,
|
||||
'tax_data' => new Response($this->mock_response),
|
||||
]);
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
@ -309,6 +310,7 @@ class UsTaxTest extends TestCase
|
||||
'shipping_country_id' => 276,
|
||||
'has_valid_vat_number' => false,
|
||||
'postal_code' => 'xx',
|
||||
'tax_data' => new Response($this->mock_response),
|
||||
]);
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
@ -353,18 +355,18 @@ class UsTaxTest extends TestCase
|
||||
{
|
||||
|
||||
$invoice = $this->invoiceStub('92582');
|
||||
$client = $invoice->client;
|
||||
$client->is_tax_exempt = false;
|
||||
$client->save();
|
||||
$invoice->client->is_tax_exempt = false;
|
||||
$invoice->client->tax_data = new Response($this->mock_response);
|
||||
|
||||
$company = $invoice->company;
|
||||
$tax_data = $company->tax_data;
|
||||
$invoice->client->push();
|
||||
|
||||
$tax_data = $invoice->company->tax_data;
|
||||
|
||||
$tax_data->regions->US->has_sales_above_threshold = true;
|
||||
$tax_data->regions->US->tax_all_subregions = true;
|
||||
|
||||
$company->tax_data = $tax_data;
|
||||
$company->save();
|
||||
$invoice->company->tax_data = $tax_data;
|
||||
$invoice->company->push();
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user