From 644c72c06afe0cbf961c69b910e68edd888a72bb Mon Sep 17 00:00:00 2001 From: Michiel Loncke <56675+webcraft@users.noreply.github.com> Date: Thu, 21 Sep 2023 15:27:42 +0200 Subject: [PATCH] Add GetTaxZoneCountry class to be able to use country based tax zones (#1248) --- .../core/src/Actions/Taxes/GetTaxZone.php | 7 ++ .../src/Actions/Taxes/GetTaxZoneCountry.php | 32 ++++++ .../Actions/Taxes/GetTaxZoneCountryTest.php | 61 ++++++++++++ .../Unit/Actions/Taxes/GetTaxZoneTest.php | 99 +++++++++++++++++++ 4 files changed, 199 insertions(+) create mode 100644 packages/core/src/Actions/Taxes/GetTaxZoneCountry.php create mode 100644 packages/core/tests/Unit/Actions/Taxes/GetTaxZoneCountryTest.php create mode 100644 packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php diff --git a/packages/core/src/Actions/Taxes/GetTaxZone.php b/packages/core/src/Actions/Taxes/GetTaxZone.php index d9c5f751fd..6ea8cf16bc 100644 --- a/packages/core/src/Actions/Taxes/GetTaxZone.php +++ b/packages/core/src/Actions/Taxes/GetTaxZone.php @@ -23,6 +23,13 @@ public function execute(Addressable $address = null) } } + if ($address && $address->country_id) { + $countryZone = app(GetTaxZoneCountry::class)->execute($address->country_id); + if ($countryZone) { + return $countryZone->taxZone; + } + } + return TaxZone::getDefault(); } } diff --git a/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php b/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php new file mode 100644 index 0000000000..892097a4fc --- /dev/null +++ b/packages/core/src/Actions/Taxes/GetTaxZoneCountry.php @@ -0,0 +1,32 @@ +getZone($countryId); + + if ($taxZone instanceof TaxZoneCountry) { + return $taxZone; + } + + if (!$taxZone) { + return null; + } + } + + /** + * Return the zone or zones which match this country. + * + * @param int $countryId + * @return TaxZoneCountry|null + */ + protected function getZone(int $countryId) + { + return TaxZoneCountry::whereCountryId($countryId)->first(); + } +} diff --git a/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneCountryTest.php b/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneCountryTest.php new file mode 100644 index 0000000000..3b6418eebc --- /dev/null +++ b/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneCountryTest.php @@ -0,0 +1,61 @@ +create([ + 'name' => 'Belgium', + ]); + + $uk = Country::factory()->create([ + 'name' => 'United Kingdom', + ]); + + $taxZoneBelgium = TaxZoneCountry::factory()->create([ + 'country_id' => $belgium->id, + ]); + + $taxZoneUk = TaxZoneCountry::factory()->create([ + 'country_id' => $uk->id, + ]); + + $zone = app(GetTaxZoneCountry::class)->execute($uk->id); + + $this->assertEquals($taxZoneUk->id, $zone->id); + } + + /** @test */ + public function can_mismatch_country_id() + { + $belgium = Country::factory()->create([ + 'name' => 'Belgium', + ]); + + $uk = Country::factory()->create([ + 'name' => 'United Kingdom', + ]); + + $taxZoneBelgium = TaxZoneCountry::factory()->create([ + 'country_id' => $belgium->id, + ]); + + $zone = app(GetTaxZoneCountry::class)->execute($uk->id); + + $this->assertNull($zone); + } +} diff --git a/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php b/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php new file mode 100644 index 0000000000..632888a346 --- /dev/null +++ b/packages/core/tests/Unit/Actions/Taxes/GetTaxZoneTest.php @@ -0,0 +1,99 @@ +create([ + 'code' => 'AL', + 'name' => 'Alabama', + ]); + + $country = Country::factory()->create([ + 'name' => 'Belgium', + ]); + + $taxZonePostcode = TaxZonePostcode::factory()->create([ + 'tax_zone_id' => TaxZone::factory(['default' => false]), + 'postcode' => $postcode, + ]); + + $taxZoneState = TaxZoneState::factory()->create([ + 'tax_zone_id' => TaxZone::factory(['default' => false]), + 'state_id' => $state->id, + ]); + + $taxZoneCountry = TaxZoneCountry::factory()->create([ + 'tax_zone_id' => TaxZone::factory(['default' => false]), + 'country_id' => $country->id, + ]); + + $defaultTaxZone = TaxZone::factory(['default' => true])->create(); + + // postcode, state and country match => postcode tax zone should be returned + $addressWithAllMatching = Address::factory()->create([ + 'postcode' => $postcode, + 'state' => $state->name, + 'country_id' => $country->id, + ]); + + $zone1 = app(GetTaxZone::class)->execute($addressWithAllMatching); + + $this->assertEquals($taxZonePostcode->tax_zone_id, $zone1->id); + + // only state and country match => state tax zone should be returned + $addressWithOnlyStateAndCountryMatching = Address::factory()->create([ + 'postcode' => '1234AB', + 'state' => $state->name, + 'country_id' => $country->id, + ]); + + $zone2 = app(GetTaxZone::class)->execute($addressWithOnlyStateAndCountryMatching); + + $this->assertEquals($taxZoneState->tax_zone_id, $zone2->id); + + // only country matches => country tax zone should be returned + $addressWithOnlyCountryMatching = Address::factory()->create([ + 'postcode' => '1234AB', + 'state' => 'Alaska', + 'country_id' => $country->id, + ]); + + $zone3 = app(GetTaxZone::class)->execute($addressWithOnlyCountryMatching); + + $this->assertEquals($taxZoneCountry->tax_zone_id, $zone3->id); + + // nothing matches => default tax zone should be returned + $addressWithOnlyCountryMatching = Address::factory()->create([ + 'postcode' => '1234AB', + 'state' => 'Alaska', + 'country_id' => 123, + ]); + + $zone3 = app(GetTaxZone::class)->execute($addressWithOnlyCountryMatching); + + $this->assertEquals($defaultTaxZone->id, $zone3->id); + } +}