Refactor for tax structure

This commit is contained in:
David Bomba 2023-03-29 13:13:50 +11:00
parent 78538c60df
commit 1ab8097d44
38 changed files with 678 additions and 299 deletions

View File

@ -11,110 +11,22 @@
namespace App\DataMapper\Tax;
use App\Models\Client;
use App\Models\Product;
use App\DataMapper\Tax\RuleInterface;
use App\DataMapper\Tax\ZipTax\Response;
use App\Models\Client;
class BaseRule implements RuleInterface
{
/** EU TAXES */
public float $vat_rate = 19;
public float $vat_threshold = 10000;
public float $vat_reduced_rate = 7;
public float $vat_reduced_threshold = 10000;
public float $at_vat_rate = 20; // Austria
public float $be_vat_rate = 21; // Belgium
public float $bg_vat_rate = 20; // Bulgaria
public float $hr_vat_rate = 25; // Croatia
public float $cy_vat_rate = 19; // Cyprus
public float $cz_vat_rate = 21; // Czech Republic
public float $dk_vat_rate = 25; // Denmark
public float $ee_vat_rate = 20; // Estonia
public float $fi_vat_rate = 24; // Finland
public float $fr_vat_rate = 20; // France
public float $de_vat_rate = 19; // Germany
public float $gr_vat_rate = 24; // Greece
public float $hu_vat_rate = 27; // Hungary
public float $ie_vat_rate = 23; // Ireland
public float $it_vat_rate = 22; // Italy
public float $lv_vat_rate = 21; // Latvia
public float $lt_vat_rate = 21; // Lithuania
public float $lu_vat_rate = 17; // Luxembourg
public float $mt_vat_rate = 18; // Malta
public float $nl_vat_rate = 21; // Netherlands
public float $pl_vat_rate = 23; // Poland
public float $pt_vat_rate = 23; // Portugal
public float $ro_vat_rate = 19; // Romania
public float $sk_vat_rate = 20; // Slovakia
public float $si_vat_rate = 22; // Slovenia
public float $es_vat_rate = 21; // Spain
public float $se_vat_rate = 25; // Sweden
public float $gb_vat_rate = 20; // United Kingdom
public bool $consumer_tax_exempt = false;
public bool $business_tax_exempt = true;
public bool $eu_business_tax_exempt = true;
public bool $foreign_business_tax_exempt = true;
public bool $foreign_consumer_tax_exempt = true;
/** EU TAXES */
/** EU TAXES */
/** US TAXES */
public float $al_sales_tax_rate = 4; // Alabama
public float $ak_sales_tax_rate = 0; // Alaska
public float $az_sales_tax_rate = 5.6; // Arizona
public float $ar_sales_tax_rate = 6.5; // Arkansas
public float $ca_sales_tax_rate = 7.25; // California - https://services.maps.cdtfa.ca.gov/api/taxrate/GetRateByAddress?address=2444+s+alameda+st&city=los+angeles&zip=90058
public float $co_sales_tax_rate = 2.9; // Colorado
public float $ct_sales_tax_rate = 6.35; // Connecticut
public float $de_sales_tax_rate = 0; // Delaware
public float $fl_sales_tax_rate = 6; // Florida
public float $ga_sales_tax_rate = 4; // Georgia
public float $hi_sales_tax_rate = 4; // Hawaii
public float $id_sales_tax_rate = 6; // Idaho
public float $il_sales_tax_rate = 6.25; // Illinois
public float $in_sales_tax_rate = 7; // Indiana
public float $ia_sales_tax_rate = 6; // Iowa
public float $ks_sales_tax_rate = 6.5; // Kansas
public float $ky_sales_tax_rate = 6; // Kentucky
public float $la_sales_tax_rate = 4.45; // Louisiana
public float $me_sales_tax_rate = 5.5; // Maine
public float $md_sales_tax_rate = 6; // Maryland
public float $ma_sales_tax_rate = 6.25; // Massachusetts
public float $mi_sales_tax_rate = 6; // Michigan
public float $mn_sales_tax_rate = 6.875; // Minnesota
public float $ms_sales_tax_rate = 7; // Mississippi
public float $mo_sales_tax_rate = 4.225; // Missouri
public float $mt_sales_tax_rate = 0; // Montana
public float $ne_sales_tax_rate = 5.5; // Nebraska
public float $nv_sales_tax_rate = 6.85; // Nevada
public float $nh_sales_tax_rate = 0; // New Hampshire
public float $nj_sales_tax_rate = 6.625; // New Jersey
public float $nm_sales_tax_rate = 5.125; // New Mexico
public float $ny_sales_tax_rate = 4; // New York
public float $nc_sales_tax_rate = 4.75; // North Carolina
public float $nd_sales_tax_rate = 5; // North Dakota
public float $oh_sales_tax_rate = 5.75; // Ohio
public float $ok_sales_tax_rate = 4.5; // Oklahoma
public float $or_sales_tax_rate = 0; // Oregon
public float $pa_sales_tax_rate = 6; // Pennsylvania
public float $ri_sales_tax_rate = 7; // Rhode Island
public float $sc_sales_tax_rate = 6; // South Carolina
public float $sd_sales_tax_rate = 4.5; // South Dakota
public float $tn_sales_tax_rate = 7; // Tennessee
public float $tx_sales_tax_rate = 6.25; // Texas
public float $ut_sales_tax_rate = 4.7; // Utah
public float $vt_sales_tax_rate = 6; // Vermont
public float $va_sales_tax_rate = 5.3; // Virginia
public float $wa_sales_tax_rate = 6.5; // Washington
public float $wv_sales_tax_rate = 6; // West Virginia
public float $wi_sales_tax_rate = 5; // Wisconsin
public float $wy_sales_tax_rate = 4; // Wyoming
public float $dc_sales_tax_rate = 6; // District of Columbia
public float $pr_sales_tax_rate = 11.5; // Puerto Rico
/**US TAXES */
/** US TAXES */
/** US TAXES */
public string $tax_name1 = '';
public float $tax_rate1 = 0;
@ -147,92 +59,48 @@ class BaseRule implements RuleInterface
return $this;
}
//need to add logic here to capture if
public function tax(): self
{
if ($this->client->is_tax_exempt || $this->client->has_valid_vat_number) {
return $this->taxExempt();
}
$this->tax_name1 = $this->vat_rate;
$this->tax_rate1 = "VAT";
return $this;
}
public function taxByType(?int $product_tax_type): self
{
if ($this->client->is_tax_exempt) {
return $this->taxExempt();
}
if (!$product_tax_type) {
return $this;
}
match ($product_tax_type) {
Product::PRODUCT_TYPE_EXEMPT => $this->taxExempt(),
Product::PRODUCT_TYPE_DIGITAL => $this->taxDigital(),
Product::PRODUCT_TYPE_SERVICE => $this->taxService(),
Product::PRODUCT_TYPE_SHIPPING => $this->taxShipping(),
Product::PRODUCT_TYPE_PHYSICAL => $this->taxPhysical(),
Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced(),
Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override(),
default => $this->default(),
};
return $this;
}
public function taxReduced(): self
{
$this->tax_rate1 = $this->vat_reduced_rate;
$this->tax_name1 = 'Reduced VAT';
return $this;
}
public function taxExempt(): self
{
$this->tax_name1 = '';
$this->tax_rate1 = 0;
return $this;
}
public function taxDigital(): self
{
$this->tax();
return $this;
}
public function taxService(): self
{
$this->tax();
return $this;
}
public function taxShipping(): self
{
$this->tax();
return $this;
}
public function taxPhysical(): self
{
$this->tax();
return $this;
}
public function default(): self
{
$this->tax_name1 = '';
$this->tax_rate1 = 0;
return $this;
}
@ -240,5 +108,4 @@ class BaseRule implements RuleInterface
{
return $this;
}
}

View File

@ -34,6 +34,8 @@ interface RuleInterface
public function default();
public function override();
public function setClient(Client $client);
public function setTaxData(Response $tax_data);

View File

@ -0,0 +1,316 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\DataMapper\Tax;
class TaxModel
{
public string $seller_region = 'US';
public string $seller_subregion = 'CA';
public object $regions;
public function __construct(public ?TaxModel $model = null)
{
if(!$this->model)
$this->regions = $this->init();
else
$this->regions = $model;
}
public function init()
{
$this->regions = new \stdClass();
$this->regions->US = new \stdClass();
$this->regions->EU = new \stdClass();
$this->usRegion()
->euRegion();
return $this->regions;
}
private function usRegion(): self
{
$this->regions->US->has_sales_above_threshold = false;
$this->regions->US->tax_all = false;
$this->usSubRegions();
return $this;
}
private function euRegion(): self
{
$this->regions->EU->has_sales_above_threshold = false;
$this->regions->EU->tax_all = false;
$this->regions->EU->vat_threshold = 10000;
$this->euSubRegions();
return $this;
}
private function usSubRegions(): self
{
$this->regions->US->subregions = new \stdClass();
$this->regions->US->subregions->AL = new \stdClass();
$this->regions->US->subregions->AL->apply_tax = false;
$this->regions->US->subregions->AK = new \stdClass();
$this->regions->US->subregions->AK->apply_tax = false;
$this->regions->US->subregions->AZ = new \stdClass();
$this->regions->US->subregions->AZ->apply_tax = false;
$this->regions->US->subregions->AR = new \stdClass();
$this->regions->US->subregions->AR->apply_tax = false;
$this->regions->US->subregions->CA = new \stdClass();
$this->regions->US->subregions->CA->apply_tax = false;
$this->regions->US->subregions->CO = new \stdClass();
$this->regions->US->subregions->CO->apply_tax = false;
$this->regions->US->subregions->CT = new \stdClass();
$this->regions->US->subregions->CT->apply_tax = false;
$this->regions->US->subregions->DE = new \stdClass();
$this->regions->US->subregions->DE->apply_tax = false;
$this->regions->US->subregions->FL = new \stdClass();
$this->regions->US->subregions->FL->apply_tax = false;
$this->regions->US->subregions->GA = new \stdClass();
$this->regions->US->subregions->GA->apply_tax = false;
$this->regions->US->subregions->HI = new \stdClass();
$this->regions->US->subregions->HI->apply_tax = false;
$this->regions->US->subregions->ID = new \stdClass();
$this->regions->US->subregions->ID->apply_tax = false;
$this->regions->US->subregions->IL = new \stdClass();
$this->regions->US->subregions->IL->apply_tax = false;
$this->regions->US->subregions->IN = new \stdClass();
$this->regions->US->subregions->IN->apply_tax = false;
$this->regions->US->subregions->IA = new \stdClass();
$this->regions->US->subregions->IA->apply_tax = false;
$this->regions->US->subregions->KS = new \stdClass();
$this->regions->US->subregions->KS->apply_tax = false;
$this->regions->US->subregions->KY = new \stdClass();
$this->regions->US->subregions->KY->apply_tax = false;
$this->regions->US->subregions->LA = new \stdClass();
$this->regions->US->subregions->LA->apply_tax = false;
$this->regions->US->subregions->ME = new \stdClass();
$this->regions->US->subregions->ME->apply_tax = false;
$this->regions->US->subregions->MD = new \stdClass();
$this->regions->US->subregions->MD->apply_tax = false;
$this->regions->US->subregions->MA = new \stdClass();
$this->regions->US->subregions->MA->apply_tax = false;
$this->regions->US->subregions->MI = new \stdClass();
$this->regions->US->subregions->MI->apply_tax = false;
$this->regions->US->subregions->MN = new \stdClass();
$this->regions->US->subregions->MN->apply_tax = false;
$this->regions->US->subregions->MS = new \stdClass();
$this->regions->US->subregions->MS->apply_tax = false;
$this->regions->US->subregions->MO = new \stdClass();
$this->regions->US->subregions->MO->apply_tax = false;
$this->regions->US->subregions->MT = new \stdClass();
$this->regions->US->subregions->MT->apply_tax = false;
$this->regions->US->subregions->NE = new \stdClass();
$this->regions->US->subregions->NE->apply_tax = false;
$this->regions->US->subregions->NV = new \stdClass();
$this->regions->US->subregions->NV->apply_tax = false;
$this->regions->US->subregions->NH = new \stdClass();
$this->regions->US->subregions->NH->apply_tax = false;
$this->regions->US->subregions->NJ = new \stdClass();
$this->regions->US->subregions->NJ->apply_tax = false;
$this->regions->US->subregions->NM = new \stdClass();
$this->regions->US->subregions->NM->apply_tax = false;
$this->regions->US->subregions->NY = new \stdClass();
$this->regions->US->subregions->NY->apply_tax = false;
$this->regions->US->subregions->NC = new \stdClass();
$this->regions->US->subregions->NC->apply_tax = false;
$this->regions->US->subregions->ND = new \stdClass();
$this->regions->US->subregions->ND->apply_tax = false;
$this->regions->US->subregions->OH = new \stdClass();
$this->regions->US->subregions->OH->apply_tax = false;
$this->regions->US->subregions->OK = new \stdClass();
$this->regions->US->subregions->OK->apply_tax = false;
$this->regions->US->subregions->OR = new \stdClass();
$this->regions->US->subregions->OR->apply_tax = false;
$this->regions->US->subregions->PA = new \stdClass();
$this->regions->US->subregions->PA->apply_tax = false;
$this->regions->US->subregions->RI = new \stdClass();
$this->regions->US->subregions->RI->apply_tax = false;
$this->regions->US->subregions->SC = new \stdClass();
$this->regions->US->subregions->SC->apply_tax = false;
$this->regions->US->subregions->SD = new \stdClass();
$this->regions->US->subregions->SD->apply_tax = false;
$this->regions->US->subregions->TN = new \stdClass();
$this->regions->US->subregions->TN->apply_tax = false;
$this->regions->US->subregions->TX = new \stdClass();
$this->regions->US->subregions->TX->apply_tax = false;
$this->regions->US->subregions->UT = new \stdClass();
$this->regions->US->subregions->UT->apply_tax = false;
$this->regions->US->subregions->VT = new \stdClass();
$this->regions->US->subregions->VT->apply_tax = false;
$this->regions->US->subregions->VA = new \stdClass();
$this->regions->US->subregions->VA->apply_tax = false;
$this->regions->US->subregions->WA = new \stdClass();
$this->regions->US->subregions->WA->apply_tax = false;
$this->regions->US->subregions->WV = new \stdClass();
$this->regions->US->subregions->WV->apply_tax = false;
$this->regions->US->subregions->WI = new \stdClass();
$this->regions->US->subregions->WI->apply_tax = false;
$this->regions->US->subregions->WY = new \stdClass();
$this->regions->US->subregions->WY->apply_tax = false;
return $this;
}
private function euSubRegions(): self
{
$this->regions->EU->subregions = new \stdClass();
$this->regions->EU->subregions->AT = new \stdClass();
$this->regions->EU->subregions->AT->vat_rate = 21;
$this->regions->EU->subregions->AT->reduced_vat_rate = 11;
$this->regions->EU->subregions->AT->apply_tax = false;
$this->regions->EU->subregions->BE = new \stdClass();
$this->regions->EU->subregions->BE->vat_rate = 21;
$this->regions->EU->subregions->BE->reduced_vat_rate = 6;
$this->regions->EU->subregions->BE->apply_tax = false;
$this->regions->EU->subregions->BG = new \stdClass();
$this->regions->EU->subregions->BG->vat_rate = 20;
$this->regions->EU->subregions->BG->reduced_vat_rate = 9;
$this->regions->EU->subregions->BG->apply_tax = false;
$this->regions->EU->subregions->CY = new \stdClass();
$this->regions->EU->subregions->CY->vat_rate = 19;
$this->regions->EU->subregions->CY->reduced_vat_rate = 9;
$this->regions->EU->subregions->CY->apply_tax = false;
$this->regions->EU->subregions->CZ = new \stdClass();
$this->regions->EU->subregions->CZ->vat_rate = 21;
$this->regions->EU->subregions->CZ->reduced_vat_rate = 15;
$this->regions->EU->subregions->CZ->apply_tax = false;
$this->regions->EU->subregions->DE = new \stdClass();
$this->regions->EU->subregions->DE->vat_rate = 19;
$this->regions->EU->subregions->DE->reduced_vat_rate = 7;
$this->regions->EU->subregions->DE->apply_tax = false;
$this->regions->EU->subregions->DK = new \stdClass();
$this->regions->EU->subregions->DK->vat_rate = 25;
$this->regions->EU->subregions->DK->reduced_vat_rate = 0;
$this->regions->EU->subregions->DK->apply_tax = false;
$this->regions->EU->subregions->EE = new \stdClass();
$this->regions->EU->subregions->EE->vat_rate = 20;
$this->regions->EU->subregions->EE->reduced_vat_rate = 9;
$this->regions->EU->subregions->EE->apply_tax = false;
$this->regions->EU->subregions->ES = new \stdClass();
$this->regions->EU->subregions->ES->vat_rate = 21;
$this->regions->EU->subregions->ES->reduced_vat_rate = 10;
$this->regions->EU->subregions->ES->apply_tax = false;
$this->regions->EU->subregions->FI = new \stdClass();
$this->regions->EU->subregions->FI->vat_rate = 24;
$this->regions->EU->subregions->FI->reduced_vat_rate = 14;
$this->regions->EU->subregions->FI->apply_tax = false;
$this->regions->EU->subregions->FR = new \stdClass();
$this->regions->EU->subregions->FR->vat_rate = 20;
$this->regions->EU->subregions->FR->reduced_vat_rate = 5.5;
$this->regions->EU->subregions->FR->apply_tax = false;
$this->regions->EU->subregions->GB = new \stdClass();
$this->regions->EU->subregions->GB->vat_rate = 20;
$this->regions->EU->subregions->GB->reduced_vat_rate = 0;
$this->regions->EU->subregions->GB->apply_tax = false;
$this->regions->EU->subregions->GR = new \stdClass();
$this->regions->EU->subregions->GR->vat_rate = 24;
$this->regions->EU->subregions->GR->reduced_vat_rate = 13;
$this->regions->EU->subregions->GR->apply_tax = false;
$this->regions->EU->subregions->HR = new \stdClass();
$this->regions->EU->subregions->HR->vat_rate = 25;
$this->regions->EU->subregions->HR->reduced_vat_rate = 5;
$this->regions->EU->subregions->HR->apply_tax = false;
$this->regions->EU->subregions->HU = new \stdClass();
$this->regions->EU->subregions->HU->vat_rate = 27;
$this->regions->EU->subregions->HU->reduced_vat_rate = 5;
$this->regions->EU->subregions->HU->apply_tax = false;
$this->regions->EU->subregions->IE = new \stdClass();
$this->regions->EU->subregions->IE->vat_rate = 23;
$this->regions->EU->subregions->IE->reduced_vat_rate = 0;
$this->regions->EU->subregions->IE->apply_tax = false;
$this->regions->EU->subregions->IT = new \stdClass();
$this->regions->EU->subregions->IT->vat_rate = 22;
$this->regions->EU->subregions->IT->reduced_vat_rate = 10;
$this->regions->EU->subregions->IT->apply_tax = false;
$this->regions->EU->subregions->LT = new \stdClass();
$this->regions->EU->subregions->LT->vat_rate = 21;
$this->regions->EU->subregions->LT->reduced_vat_rate = 9;
$this->regions->EU->subregions->LT->apply_tax = false;
$this->regions->EU->subregions->LU = new \stdClass();
$this->regions->EU->subregions->LU->vat_rate = 17;
$this->regions->EU->subregions->LU->reduced_vat_rate = 3;
$this->regions->EU->subregions->LU->apply_tax = false;
$this->regions->EU->subregions->LV = new \stdClass();
$this->regions->EU->subregions->LV->vat_rate = 21;
$this->regions->EU->subregions->LV->reduced_vat_rate = 12;
$this->regions->EU->subregions->LV->apply_tax = false;
$this->regions->EU->subregions->MT = new \stdClass();
$this->regions->EU->subregions->MT->vat_rate = 18;
$this->regions->EU->subregions->MT->reduced_vat_rate = 5;
$this->regions->EU->subregions->MT->apply_tax = false;
$this->regions->EU->subregions->NL = new \stdClass();
$this->regions->EU->subregions->NL->vat_rate = 21;
$this->regions->EU->subregions->NL->reduced_vat_rate = 9;
$this->regions->EU->subregions->NL->apply_tax = false;
$this->regions->EU->subregions->PT = new \stdClass();
$this->regions->EU->subregions->PT->vat_rate = 23;
$this->regions->EU->subregions->PT->reduced_vat_rate = 6;
$this->regions->EU->subregions->PT->apply_tax = false;
$this->regions->EU->subregions->RO = new \stdClass();
$this->regions->EU->subregions->RO->vat_rate = 19;
$this->regions->EU->subregions->RO->reduced_vat_rate = 5;
$this->regions->EU->subregions->RO->apply_tax = false;
$this->regions->EU->subregions->SE = new \stdClass();
$this->regions->EU->subregions->SE->vat_rate = 25;
$this->regions->EU->subregions->SE->reduced_vat_rate = 12;
$this->regions->EU->subregions->SE->apply_tax = false;
$this->regions->EU->subregions->SI = new \stdClass();
$this->regions->EU->subregions->SI->vat_rate = 22;
$this->regions->EU->subregions->SI->reduced_vat_rate = 9.5;
$this->regions->EU->subregions->SI->apply_tax = false;
$this->regions->EU->subregions->SK = new \stdClass();
$this->regions->EU->subregions->SK->vat_rate = 20;
$this->regions->EU->subregions->SK->reduced_vat_rate = 10;
$this->regions->EU->subregions->SK->apply_tax = false;
return $this;
}
}

View File

@ -57,6 +57,8 @@ class Response
* ];
*
*/
public string $seller_region = "";
//US
public string $geoPostalCode = "";
public string $geoCity = "";
@ -93,6 +95,13 @@ class Response
public float $district5UseTax = 0;
public string $originDestination = "";
//EU
public float $vat_rate = 0;
public float $vat_reduced_rate = 0;
public string $vat_country_code = "";
public function __construct($data)
{

View File

@ -20,17 +20,9 @@ use App\DataMapper\Tax\ZipTax\Response;
class Rule extends BaseRule implements RuleInterface
{
public float $vat_rate = 19;
public float $vat_threshold = 10000;
public float $vat_reduced_rate = 7;
public float $vat_reduced_threshold = 10000;
public bool $consumer_tax_exempt = false;
public bool $business_tax_exempt = true;
public bool $business_tax_exempt = false;
public bool $eu_business_tax_exempt = true;
@ -102,6 +94,7 @@ class Rule extends BaseRule implements RuleInterface
Product::PRODUCT_TYPE_SHIPPING => $this->taxShipping(),
Product::PRODUCT_TYPE_PHYSICAL => $this->taxPhysical(),
Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced(),
Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override(),
default => $this->default(),
};
@ -160,4 +153,10 @@ class Rule extends BaseRule implements RuleInterface
return $this;
}
public function override(): self
{
return $this;
}
}

View File

@ -2,217 +2,219 @@ region:
US:
tax_all: false
seller_region: CA
has_sales_above_threshold: false
subregions:
AL:
APPLY_TAX: false
apply_tax: false
AK:
APPLY_TAX: false
apply_tax: false
AZ:
APPLY_TAX: false
apply_tax: false
AR:
APPLY_TAX: false
apply_tax: false
CA:
APPLY_TAX: false
apply_tax: false
CO:
APPLY_TAX: false
apply_tax: false
CT:
APPLY_TAX: false
apply_tax: false
DE:
APPLY_TAX: false
apply_tax: false
FL:
APPLY_TAX: false
apply_tax: false
GA:
APPLY_TAX: false
apply_tax: false
HI:
APPLY_TAX: false
apply_tax: false
ID:
APPLY_TAX: false
apply_tax: false
IL:
APPLY_TAX: false
apply_tax: false
IN:
APPLY_TAX: false
apply_tax: false
IA:
APPLY_TAX: false
apply_tax: false
KS:
APPLY_TAX: false
apply_tax: false
KY:
APPLY_TAX: false
apply_tax: false
LA:
APPLY_TAX: false
apply_tax: false
ME:
APPLY_TAX: false
apply_tax: false
MD:
APPLY_TAX: false
apply_tax: false
MA:
APPLY_TAX: false
apply_tax: false
MI:
APPLY_TAX: false
apply_tax: false
MN:
APPLY_TAX: false
apply_tax: false
MS:
APPLY_TAX: false
apply_tax: false
MO:
APPLY_TAX: false
apply_tax: false
MT:
APPLY_TAX: false
apply_tax: false
NE:
APPLY_TAX: false
apply_tax: false
NV:
APPLY_TAX: false
apply_tax: false
NH:
APPLY_TAX: false
apply_tax: false
NJ:
APPLY_TAX: false
apply_tax: false
NM:
APPLY_TAX: false
apply_tax: false
NY:
APPLY_TAX: false
apply_tax: false
NC:
APPLY_TAX: false
apply_tax: false
ND:
APPLY_TAX: false
apply_tax: false
OH:
APPLY_TAX: false
apply_tax: false
OK:
APPLY_TAX: false
apply_tax: false
OR:
APPLY_TAX: false
apply_tax: false
PA:
APPLY_TAX: false
apply_tax: false
RI:
APPLY_TAX: false
apply_tax: false
SC:
APPLY_TAX: false
apply_tax: false
SD:
APPLY_TAX: false
apply_tax: false
TN:
APPLY_TAX: false
apply_tax: false
TX:
APPLY_TAX: false
apply_tax: false
UT:
APPLY_TAX: false
apply_tax: false
VT:
APPLY_TAX: false
apply_tax: false
VA:
APPLY_TAX: false
apply_tax: false
WA:
APPLY_TAX: false
apply_tax: false
WV:
APPLY_TAX: false
apply_tax: false
WI:
APPLY_TAX: false
apply_tax: false
WY:
APPLY_TAX: false
apply_tax: false
EU:
tax_all: false
vat_threshold: 10000
has_sales_above_threshold: false
seller_region: DE
subregions:
AT:
VAT: 21
REDUCED_VAT: 11
APPLY_VAT: false
vat: 21
reduced_vat: 11
apply_tax: false
BE:
VAT: 21
REDUCED_VAT: 6
APPLY_VAT: false
vat: 21
reduced_vat: 6
apply_tax: false
BG:
VAT: 20
REDUCED_VAT: 9
APPLY_VAT: false
vat: 20
reduced_vat: 9
apply_tax: false
CY:
VAT: 19
REDUCED_VAT: 9
APPLY_VAT: false
vat: 19
reduced_vat: 9
apply_tax: false
CZ:
VAT: 21
REDUCED_VAT: 15
APPLY_VAT: false
vat: 21
reduced_vat: 15
apply_tax: false
DE:
VAT: 19
REDUCED_VAT: 7
APPLY_VAT: false
vat: 19
reduced_vat: 7
apply_tax: false
DK:
VAT: 25
REDUCED_VAT: 0
APPLY_VAT: false
vat: 25
reduced_vat: 0
apply_tax: false
EE:
VAT: 20
REDUCED_VAT: 9
APPLY_VAT: false
vat: 20
reduced_vat: 9
apply_tax: false
ES:
VAT: 21
REDUCED_VAT: 10
APPLY_VAT: false
vat: 21
reduced_vat: 10
apply_tax: false
FI:
VAT: 24
REDUCED_VAT: 14
APPLY_VAT: false
vat: 24
reduced_vat: 14
apply_tax: false
FR:
VAT: 20
REDUCED_VAT: 5.5
APPLY_VAT: false
vat: 20
reduced_vat: 5.5
apply_tax: false
GB:
VAT: 20
REDUCED_VAT: 0
APPLY_VAT: false
vat: 20
reduced_vat: 0
apply_tax: false
GR:
VAT: 24
REDUCED_VAT: 13
APPLY_VAT: false
vat: 24
reduced_vat: 13
apply_tax: false
HR:
VAT: 25
REDUCED_VAT: 5
APPLY_VAT: false
vat: 25
reduced_vat: 5
apply_tax: false
HU:
VAT: 27
REDUCED_VAT: 5
APPLY_VAT: false
vat: 27
reduced_vat: 5
apply_tax: false
IE:
VAT: 23
REDUCED_VAT: 0
APPLY_VAT: false
vat: 23
reduced_vat: 0
apply_tax: false
IT:
VAT: 22
REDUCED_VAT: 10
APPLY_VAT: false
vat: 22
reduced_vat: 10
apply_tax: false
LT:
VAT: 21
REDUCED_VAT: 9
APPLY_VAT: false
vat: 21
reduced_vat: 9
apply_tax: false
LU:
VAT: 17
REDUCED_VAT: 3
APPLY_VAT: false
vat: 17
reduced_vat: 3
apply_tax: false
LV:
VAT: 21
REDUCED_VAT: 12
APPLY_VAT: false
vat: 21
reduced_vat: 12
apply_tax: false
MT:
VAT: 18
REDUCED_VAT: 5
APPLY_VAT: false
vat: 18
reduced_vat: 5
apply_tax: false
NL:
VAT: 21
REDUCED_VAT: 9
APPLY_VAT: false
vat: 21
reduced_vat: 9
apply_tax: false
PT:
VAT: 23
REDUCED_VAT: 6
APPLY_VAT: false
vat: 23
reduced_vat: 6
apply_tax: false
RO:
VAT: 19
REDUCED_VAT: 5
APPLY_VAT: false
vat: 19
reduced_vat: 5
apply_tax: false
SE:
VAT: 25
REDUCED_VAT: 12
APPLY_VAT: false
vat: 25
reduced_vat: 12
apply_tax: false
SI:
VAT: 22
REDUCED_VAT: 9.5
APPLY_VAT: false
vat: 22
reduced_vat: 9.5
apply_tax: false
SK:
VAT: 20
REDUCED_VAT: 10
APPLY_VAT: false
vat: 20
reduced_vat: 10
apply_tax: false

View File

@ -36,6 +36,11 @@ class Rule implements RuleInterface
{
}
public function override()
{
return $this;
}
public function setTaxData(Response $tax_data): self
{
$this->tax_data = $tax_data;
@ -78,6 +83,8 @@ class Rule implements RuleInterface
Product::PRODUCT_TYPE_SERVICE => $this->taxService(),
Product::PRODUCT_TYPE_SHIPPING => $this->taxShipping(),
Product::PRODUCT_TYPE_PHYSICAL => $this->taxPhysical(),
Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced(),
Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override(),
default => $this->default(),
};

View File

@ -154,6 +154,10 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @mixin \Eloquent
*/
class Account extends BaseModel

View File

@ -38,6 +38,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankSubaccount> $bank_subaccounts
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankSubaccount> $bank_subaccounts
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankSubaccount> $bank_subaccounts
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankSubaccount> $bank_subaccounts
* @mixin \Eloquent
*/
class BankAccount extends BaseModel

View File

@ -81,6 +81,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankTransaction> $transactions
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankTransaction> $transactions
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankTransaction> $transactions
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankTransaction> $transactions
* @mixin \Eloquent
*/
class BankIntegration extends BaseModel

View File

@ -274,6 +274,23 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoice> $recurring_invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\SystemLog> $system_logs
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientContact> $contacts
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Expense> $expenses
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientGatewayToken> $gateway_tokens
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Payment> $payments
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientContact> $primary_contact
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Project> $projects
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Quote> $quotes
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringExpense> $recurring_expenses
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoice> $recurring_invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\SystemLog> $system_logs
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
* @mixin \Eloquent
*/
class Client extends BaseModel implements HasLocalePreference

View File

@ -153,6 +153,11 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $credit_invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invoice_invitations
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $quote_invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $recurring_invoice_invitations
* @mixin \Eloquent
*/
class ClientContact extends Authenticatable implements HasLocalePreference

View File

@ -552,6 +552,50 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Vendor> $vendors
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Webhook> $webhooks
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $all_activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $all_documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankIntegration> $bank_integrations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankTransactionRule> $bank_transaction_rules
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\BankTransaction> $bank_transactions
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientContact> $client_contacts
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientGatewayToken> $client_gateway_tokens
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Client> $clients
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyGateway> $company_gateways
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientContact> $contacts
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Design> $designs
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ExpenseCategory> $expense_categories
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Expense> $expenses
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\GroupSetting> $group_settings
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\GroupSetting> $groups
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentTerm> $payment_terms
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Payment> $payments
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Product> $products
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Project> $projects
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PurchaseOrder> $purchase_orders
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Quote> $quotes
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringExpense> $recurring_expenses
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoice> $recurring_invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Scheduler> $schedulers
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Subscription> $subscriptions
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\SystemLog> $system_log_relation
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\SystemLog> $system_logs
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Scheduler> $task_schedulers
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\TaskStatus> $task_statuses
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\TaxRate> $tax_rates
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyToken> $tokens
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyToken> $tokens_hashed
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Design> $user_designs
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentTerm> $user_payment_terms
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Vendor> $vendors
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Webhook> $webhooks
* @mixin \Eloquent
*/
class Company extends BaseModel

View File

@ -98,6 +98,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientGatewayToken> $client_gateway_tokens
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientGatewayToken> $client_gateway_tokens
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientGatewayToken> $client_gateway_tokens
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientGatewayToken> $client_gateway_tokens
* @mixin \Eloquent
*/
class CompanyGateway extends BaseModel

View File

@ -85,6 +85,9 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyToken> $token
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyToken> $tokens
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyToken> $token
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyToken> $tokens
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
* @mixin \Eloquent
*/
class CompanyUser extends Pivot

View File

@ -227,6 +227,13 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Payment> $payments
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CreditInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Payment> $payments
* @mixin \Eloquent
*/
class Credit extends BaseModel

View File

@ -136,6 +136,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @mixin \Eloquent
*/
class Expense extends BaseModel

View File

@ -34,6 +34,7 @@ namespace App\Models;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PaymentType> $payment_methods
* @mixin \Eloquent
*/
class GatewayType extends StaticModel

View File

@ -66,6 +66,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Client> $clients
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Client> $clients
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @mixin \Eloquent
*/
class GroupSetting extends StaticModel

View File

@ -259,6 +259,15 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Payment> $payments
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Expense> $expenses
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\InvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Payment> $payments
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
* @mixin \Eloquent
*/
class Invoice extends BaseModel

View File

@ -162,6 +162,11 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyLedger> $company_ledger
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Credit> $credits
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Paymentable> $paymentables
* @mixin \Eloquent
*/
class Payment extends BaseModel

View File

@ -104,6 +104,7 @@ use League\CommonMark\CommonMarkConverter;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @mixin \Eloquent
*/
class Product extends BaseModel

View File

@ -84,6 +84,8 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Task> $tasks
* @mixin \Eloquent
*/
class Project extends BaseModel

View File

@ -34,6 +34,7 @@ use App\Utils\Traits\MakesHash;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @mixin \Eloquent
*/
class Proposal extends BaseModel

View File

@ -216,6 +216,12 @@ use Illuminate\Support\Facades\Storage;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PurchaseOrderInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Payment> $payments
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PurchaseOrderInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Payment> $payments
* @mixin \Eloquent
*/
class PurchaseOrder extends BaseModel

View File

@ -205,6 +205,10 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\QuoteInvitation> $invitations
* @mixin \Eloquent
*/
class Quote extends BaseModel

View File

@ -145,6 +145,7 @@ use Illuminate\Support\Carbon;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @mixin \Eloquent
*/
class RecurringExpense extends BaseModel

View File

@ -209,6 +209,11 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringInvoiceInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Invoice> $invoices
* @mixin \Eloquent
*/
class RecurringInvoice extends BaseModel

View File

@ -201,6 +201,11 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringQuoteInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Quote> $quotes
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Backup> $history
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\RecurringQuoteInvitation> $invitations
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Quote> $quotes
* @mixin \Eloquent
*/
class RecurringQuote extends BaseModel

View File

@ -97,6 +97,7 @@ use Illuminate\Support\Carbon;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @mixin \Eloquent
*/
class Task extends BaseModel

View File

@ -181,6 +181,13 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyToken> $tokens
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Client> $clients
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Company> $companies
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyUser> $company_users
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ClientContact> $contacts
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\CompanyToken> $tokens
* @mixin \Eloquent
*/
class User extends Authenticatable implements MustVerifyEmail

View File

@ -128,6 +128,10 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Activity> $activities
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $contacts
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\VendorContact> $primary_contact
* @mixin \Eloquent
*/
class Vendor extends BaseModel

View File

@ -122,6 +122,8 @@ use Laracasts\Presenter\PresentableTrait;
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PurchaseOrderInvitation> $purchase_order_invitations
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PurchaseOrderInvitation> $purchase_order_invitations
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PurchaseOrderInvitation> $purchase_order_invitations
* @mixin \Eloquent
*/
class VendorContact extends Authenticatable implements HasLocalePreference

View File

@ -28,7 +28,7 @@ class EuTax
private float $vat_rate = 0.0;
private float $vat_reduced_rate = 0.0;
private float $reduced_vat_rate = 0.0;
private array $eu_country_codes = [
'AT', // Austria
@ -86,7 +86,7 @@ class EuTax
public function getVatReducedRate(): float
{
return $this->vat_reduced_rate;
return $this->reduced_vat_rate;
}
public function getVendorCountryCode(): string
@ -125,29 +125,41 @@ class EuTax
{
if(
(($this->vendor_country_code == $this->client_country_code) && $this->valid_vat_number && $this->rule->business_tax_exempt) ||
(in_array($this->client_country_code, $this->eu_country_codes) && $this->valid_vat_number && $this->rule->business_tax_exempt)
(($this->vendor_country_code == $this->client_country_code) && $this->valid_vat_number && $this->rule->business_tax_exempt) || //same country / exempt for tax / valid vat number
(in_array($this->client_country_code, $this->eu_country_codes) && $this->valid_vat_number && $this->rule->eu_business_tax_exempt) //eu country / exempt for tax / valid vat number
) {
$this->vat_rate = 0.0;
$this->vat_reduced_rate = 0.0;
$this->vat_rate = 0;
$this->reduced_vat_rate = 0;
nlog("euro zone and tax exempt");
}
elseif(!in_array(strtoupper($this->client_country_code), $this->eu_country_codes) && ($this->rule->foreign_consumer_tax_exempt || $this->rule->foreign_business_tax_exempt)) {
nlog($this->client_country_code);
$this->vat_rate = 0.0;
$this->vat_reduced_rate = 0.0;
elseif(!in_array(strtoupper($this->client_country_code), $this->eu_country_codes) && ($this->rule->foreign_consumer_tax_exempt || $this->rule->foreign_business_tax_exempt)) //foreign + tax exempt
{
$this->vat_rate = 0;
$this->reduced_vat_rate = 0;
nlog("foreign and tax exempt");
}
elseif(in_array(strtoupper($this->client_country_code), $this->eu_country_codes) && !$this->valid_vat_number) {
$rate_name = $this->client_country_code."_vat_rate";
$this->vat_rate = $this->rule->{$rate_name};
$this->vat_reduced_rate = $this->rule->vat_reduced_rate;
elseif(in_array(strtoupper($this->client_country_code), $this->eu_country_codes) && !$this->valid_vat_number) //eu country / no valid vat
{
if(($this->vendor_country_code != $this->client_country_code) && $this->company->tax_data->regions->EU->has_sales_above_threshold)
{
$this->vat_rate = $this->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->vat_rate;
$this->reduced_vat_rate = $this->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_vat_rate;
nlog("eu zone with sales above threshold");
}
else {
$this->vat_rate = $this->company->tax_data->regions->EU->subregions->{$this->company->country()->iso_3166_2}->vat_rate;
$this->reduced_vat_rate = $this->company->tax_data->regions->EU->subregions->{$this->company->country()->iso_3166_2}->reduced_vat_rate;
nlog("same eu country with");
}
}
else {
$rate_name = $this->vendor_country_code."_vat_rate";
$this->vat_rate = $this->rule->{$rate_name};
$this->vat_reduced_rate = $this->rule->vat_reduced_rate;
nlog("default tax");
$this->vat_rate = $this->company->tax_data->regions->EU->subregions->{$this->company->country()->iso_3166_2}->vat_rate;
$this->reduced_vat_rate = $this->company->tax_data->regions->EU->subregions->{$this->company->country()->iso_3166_2}->reduced_vat_rate;
}
return $this;
}
}

View File

@ -149,6 +149,7 @@ class ClientTransformer extends EntityTransformer
'number' => (string) $client->number ?: '',
'has_valid_vat_number' => (bool) $client->has_valid_vat_number,
'is_tax_exempt' => (bool) $client->is_tax_exempt,
'tax_data' => $client->tax_data ?: '',
];
}
}

View File

@ -195,6 +195,7 @@ class CompanyTransformer extends EntityTransformer
'invoice_task_hours' => (bool) $company->invoice_task_hours,
'calculate_taxes' => (bool) $company->calculate_taxes,
'tax_all_products' => (bool) $company->tax_all_products,
'tax_data' => $company->tax_data ?: '',
];
}

View File

@ -13,10 +13,17 @@ return new class extends Migration
*/
public function up()
{
Schema::table('clients', function (Blueprint $table) {
Schema::table('clients', function (Illuminate\Database\Schema\Blueprint $table) {
$table->boolean('is_tax_exempt')->default(false);
$table->boolean('has_valid_vat_number')->default(false);
$table->mediumText('tax_data')->nullable()->change();
});
Schema::table('companies', function (Illuminate\Database\Schema\Blueprint $table) {
$table->mediumText('tax_data')->nullable()->change();
});
}
/**

View File

@ -16,8 +16,9 @@ use App\Models\Client;
use App\Models\Company;
use Tests\MockAccountData;
use App\DataMapper\Tax\de\Rule;
use App\Services\Tax\Providers\EuTax;
use App\DataMapper\Tax\TaxModel;
use App\DataMapper\CompanySettings;
use App\Services\Tax\Providers\EuTax;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Foundation\Testing\DatabaseTransactions;
@ -48,9 +49,16 @@ class EuTaxTest extends TestCase
$settings = CompanySettings::defaults();
$settings->country_id = '276'; // germany
$tax_data = new TaxModel();
$tax_data->seller_region = 'DE';
$tax_data->seller_subregion = 'DE';
$tax_data->regions->EU->has_sales_above_threshold = true;
$tax_data->regions->EU->tax_all = true;
$company = Company::factory()->create([
'account_id' => $this->account->id,
'settings' => $settings
'settings' => $settings,
'tax_data' => $tax_data,
]);
$client = Client::factory()->create([
@ -84,11 +92,19 @@ class EuTaxTest extends TestCase
$settings = CompanySettings::defaults();
$settings->country_id = '276'; // germany
$tax_data = new TaxModel();
$tax_data->seller_region = 'DE';
$tax_data->seller_subregion = 'DE';
$tax_data->regions->EU->has_sales_above_threshold = true;
$tax_data->regions->EU->tax_all = true;
$company = Company::factory()->create([
'account_id' => $this->account->id,
'settings' => $settings
'settings' => $settings,
'tax_data' => $tax_data,
]);
$client = Client::factory()->create([
'user_id' => $this->user->id,
'company_id' => $company->id,
@ -109,7 +125,7 @@ class EuTaxTest extends TestCase
$this->assertEquals(21, $process->getVatRate());
$this->assertEquals(7, $process->getVatReducedRate());
$this->assertEquals(6, $process->getVatReducedRate());
}