diff --git a/app/DataMapper/Tax/BaseRule.php b/app/DataMapper/Tax/BaseRule.php index 903cbb155f3b..5b0b6c87dce7 100644 --- a/app/DataMapper/Tax/BaseRule.php +++ b/app/DataMapper/Tax/BaseRule.php @@ -12,6 +12,7 @@ namespace App\DataMapper\Tax; use App\Models\Client; +use App\Models\Invoice; use App\Models\Product; use App\DataMapper\Tax\ZipTax\Response; @@ -117,6 +118,8 @@ class BaseRule implements RuleInterface protected ?Response $tax_data; + public ?Invoice $invoice; + public function __construct() { } @@ -126,18 +129,16 @@ class BaseRule implements RuleInterface return $this; } - public function setClient(Client $client): self + public function setInvoice(Invoice $invoice): self { - $this->client = $client; + $this->invoice = $invoice; + + $this->client = $invoice->client; + + $this->tax_data = new Response($invoice?->tax_data); $this->resolveRegions(); - return $this; - } - - public function setTaxData(Response $tax_data): self - { - $this->tax_data = $tax_data; return $this; } @@ -176,10 +177,10 @@ class BaseRule implements RuleInterface return $this; } - elseif($this->client_region == 'AU'){ + elseif($this->client_region == 'AU'){ //these are defaults and are only stubbed out for now, for AU we can actually remove these - $this->tax_rate1 = 10; - $this->tax_name1 = 'GST'; + $this->tax_rate1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_rate; + $this->tax_name1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_name; return $this; } diff --git a/app/DataMapper/Tax/TaxModel.php b/app/DataMapper/Tax/TaxModel.php index b6baf1c74d1f..21b811898d2b 100644 --- a/app/DataMapper/Tax/TaxModel.php +++ b/app/DataMapper/Tax/TaxModel.php @@ -14,19 +14,19 @@ namespace App\DataMapper\Tax; class TaxModel { - /** @var mixed $seller_subregion */ + /** @var string $seller_subregion */ public string $seller_subregion = 'CA'; - /** @var mixed $version */ + /** @var string $version */ public string $version = 'alpha'; - /** @var mixed $regions */ + /** @var object $regions */ public object $regions; /** * __construct * - * @param mixed $model + * @param TaxModel $model * @return void */ public function __construct(public ?TaxModel $model = null) @@ -42,9 +42,9 @@ class TaxModel /** * Initializes the rules and builds any required data. * - * @return void + * @return object */ - public function init() + public function init(): object { $this->regions = new \stdClass(); $this->regions->US = new \stdClass(); diff --git a/app/DataMapper/Tax/ZipTax/Response.php b/app/DataMapper/Tax/ZipTax/Response.php index 1358fccb2d6c..6fbed6ed72f5 100644 --- a/app/DataMapper/Tax/ZipTax/Response.php +++ b/app/DataMapper/Tax/ZipTax/Response.php @@ -65,6 +65,7 @@ class Response public string $geoCounty = ""; public string $geoState = ""; public float $taxSales = 0; + public string $taxName = ""; public float $taxUse = 0; public string $txbService = ""; // N = No, Y = Yes public string $txbFreight = ""; // N = No, Y = Yes @@ -73,6 +74,8 @@ class Response public float $citySalesTax = 0; public float $cityUseTax = 0; public string $cityTaxCode = ""; + + /* US SPECIFIC TAX CODES */ public float $countySalesTax = 0; public float $countyUseTax = 0; public string $countyTaxCode = ""; @@ -93,7 +96,9 @@ class Response public string $district5Code = ""; public float $district5SalesTax = 0; public float $district5UseTax = 0; - public string $originDestination = ""; + /* US SPECIFIC TAX CODES */ + + public string $originDestination = ""; // defines if the client origin is the locale where the tax is remitted to public function __construct($data) { diff --git a/app/Helpers/Invoice/InvoiceItemSum.php b/app/Helpers/Invoice/InvoiceItemSum.php index f3cfc2cf7427..afef994e2ba0 100644 --- a/app/Helpers/Invoice/InvoiceItemSum.php +++ b/app/Helpers/Invoice/InvoiceItemSum.php @@ -146,12 +146,9 @@ class InvoiceItemSum $class = "App\DataMapper\Tax\\".$this->client->company->country()->iso_3166_2."\\Rule"; - $tax_data = new Response($this->invoice?->tax_data); - $this->rule = new $class(); $this->rule - ->setTaxData($tax_data) - ->setClient($this->client) + ->setInvoice($this->invoice) ->init(); $this->calc_tax = true; diff --git a/app/Repositories/BaseRepository.php b/app/Repositories/BaseRepository.php index 3678a789829a..0439fa59d11a 100644 --- a/app/Repositories/BaseRepository.php +++ b/app/Repositories/BaseRepository.php @@ -190,7 +190,7 @@ class BaseRepository $this->new_model = true; if (is_array($model->line_items) && !($model instanceof RecurringInvoice)) { - $model->line_items = (collect($model->line_items))->map(function ($item) use ($model, $client) { + $model->line_items = (collect($model->line_items))->map(function ($item) use ($client) { $item->notes = Helpers::processReservedKeywords($item->notes, $client); return $item; diff --git a/tests/Unit/Tax/EuTaxTest.php b/tests/Unit/Tax/EuTaxTest.php index 3368ab935add..6f41d282bbc3 100644 --- a/tests/Unit/Tax/EuTaxTest.php +++ b/tests/Unit/Tax/EuTaxTest.php @@ -11,18 +11,18 @@ namespace Tests\Unit\Tax; -use Tests\TestCase; +use App\DataMapper\CompanySettings; +use App\DataMapper\Tax\DE\Rule; +use App\DataMapper\Tax\TaxModel; +use App\DataMapper\Tax\ZipTax\Response; use App\Models\Client; use App\Models\Company; use App\Models\Invoice; use App\Models\Product; -use Tests\MockAccountData; -use App\DataMapper\Tax\DE\Rule; -use App\DataMapper\Tax\TaxModel; -use App\DataMapper\CompanySettings; -use App\DataMapper\Tax\ZipTax\Response; -use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Foundation\Testing\DatabaseTransactions; +use Illuminate\Routing\Middleware\ThrottleRequests; +use Tests\MockAccountData; +use Tests\TestCase; /** * @test App\Services\Tax\Providers\EuTax @@ -338,8 +338,18 @@ class EuTaxTest extends TestCase 'has_valid_vat_number' => false, ]); + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'status_id' => Invoice::STATUS_SENT, + 'tax_data' => new Response([ + 'geoState' => 'CA', + ]), + ]); + $process = new Rule(); - $process->setClient($client); + $process->setInvoice($invoice); $process->init(); $this->assertEquals('EU', $process->seller_region); @@ -382,12 +392,21 @@ class EuTaxTest extends TestCase 'has_valid_vat_number' => false, ]); + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'status_id' => Invoice::STATUS_SENT, + 'tax_data' => new Response([ + 'geoState' => 'CA', + ]), + ]); + $process = new Rule(); - $process->setClient($client); + $process->setInvoice($invoice); $process->init(); - -$this->assertEquals('EU', $process->seller_region); + $this->assertEquals('EU', $process->seller_region); $this->assertEquals('BE', $process->client_subregion); @@ -428,11 +447,18 @@ $this->assertEquals('EU', $process->seller_region); 'has_valid_vat_number' => false, ]); + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'status_id' => Invoice::STATUS_SENT, + 'tax_data' => new Response([ + 'geoState' => 'CA', + ]), + ]); + $process = new Rule(); - $process->setTaxData(new Response([ - 'geoState' => 'CA', - ])); - $process->setClient($client); + $process->setInvoice($invoice); $process->init(); $this->assertEquals('EU', $process->seller_region); @@ -476,8 +502,18 @@ $this->assertEquals('EU', $process->seller_region); 'has_valid_vat_number' => false, ]); + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'status_id' => Invoice::STATUS_SENT, + 'tax_data' => new Response([ + 'geoState' => 'CA', + ]), + ]); + $process = new Rule(); - $process->setClient($client); + $process->setInvoice($invoice); $process->init(); $this->assertInstanceOf(Rule::class, $process); @@ -517,10 +553,21 @@ $this->assertEquals('EU', $process->seller_region); 'has_valid_vat_number' => true, ]); + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'status_id' => Invoice::STATUS_SENT, + 'tax_data' => new Response([ + 'geoState' => 'CA', + ]), + ]); + $process = new Rule(); - $process->setClient($client); + $process->setInvoice($invoice); $process->init(); + $this->assertInstanceOf(Rule::class, $process); $this->assertTrue($client->has_valid_vat_number); @@ -556,11 +603,22 @@ $this->assertEquals('EU', $process->seller_region); 'shipping_country_id' => 56, 'has_valid_vat_number' => true, ]); + + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'status_id' => Invoice::STATUS_SENT, + 'tax_data' => new Response([ + 'geoState' => 'CA', + ]), + ]); $process = new Rule(); - $process->setClient($client); + $process->setInvoice($invoice); $process->init(); + $this->assertInstanceOf(Rule::class, $process); $this->assertTrue($client->has_valid_vat_number); @@ -597,10 +655,21 @@ $this->assertEquals('EU', $process->seller_region); 'is_tax_exempt' => true, ]); + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'status_id' => Invoice::STATUS_SENT, + 'tax_data' => new Response([ + 'geoState' => 'CA', + ]), + ]); + $process = new Rule(); - $process->setClient($client); + $process->setInvoice($invoice); $process->init(); + $this->assertInstanceOf(Rule::class, $process); $this->assertTrue($client->is_tax_exempt); @@ -637,8 +706,18 @@ $this->assertEquals('EU', $process->seller_region); 'is_tax_exempt' => true, ]); + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'status_id' => Invoice::STATUS_SENT, + 'tax_data' => new Response([ + 'geoState' => 'CA', + ]), + ]); + $process = new Rule(); - $process->setClient($client); + $process->setInvoice($invoice); $process->init(); $this->assertInstanceOf(Rule::class, $process); @@ -676,11 +755,21 @@ $this->assertEquals('EU', $process->seller_region); 'is_tax_exempt' => true, ]); + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'client_id' => $client->id, + 'user_id' => $this->user->id, + 'status_id' => Invoice::STATUS_SENT, + 'tax_data' => new Response([ + 'geoState' => 'CA', + ]), + ]); + $process = new Rule(); - $process->setTaxData(new Response([])); - $process->setClient($client); + $process->setInvoice($invoice); $process->init(); + $this->assertInstanceOf(Rule::class, $process); $this->assertTrue($client->is_tax_exempt);