mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge pull request #8425 from turbo124/v5-develop
Set default tax id for products
This commit is contained in:
commit
87442190a8
@ -59,7 +59,11 @@ class InvoiceItem
|
||||
|
||||
public $type_id = '1'; //1 = product, 2 = service, 3 unpaid gateway fee, 4 paid gateway fee, 5 late fee, 6 expense
|
||||
|
||||
public $tax_id = '';
|
||||
|
||||
|
||||
public static $casts = [
|
||||
'tax_id' => 'string',
|
||||
'type_id' => 'string',
|
||||
'quantity' => 'float',
|
||||
'cost' => 'float',
|
||||
|
156
app/DataMapper/Tax/BaseRule.php
Normal file
156
app/DataMapper/Tax/BaseRule.php
Normal file
@ -0,0 +1,156 @@
|
||||
<?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;
|
||||
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
use App\Models\Client;
|
||||
|
||||
class BaseRule implements RuleInterface
|
||||
{
|
||||
/** EU TAXES */
|
||||
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;
|
||||
|
||||
public array $eu_country_codes = [
|
||||
'AT', // Austria
|
||||
'BE', // Belgium
|
||||
'BG', // Bulgaria
|
||||
'CY', // Cyprus
|
||||
'CZ', // Czech Republic
|
||||
'DE', // Germany
|
||||
'DK', // Denmark
|
||||
'EE', // Estonia
|
||||
'ES', // Spain
|
||||
'FI', // Finland
|
||||
'FR', // France
|
||||
'GR', // Greece
|
||||
'HR', // Croatia
|
||||
'HU', // Hungary
|
||||
'IE', // Ireland
|
||||
'IT', // Italy
|
||||
'LT', // Lithuania
|
||||
'LU', // Luxembourg
|
||||
'LV', // Latvia
|
||||
'MT', // Malta
|
||||
'NL', // Netherlands
|
||||
'PL', // Poland
|
||||
'PT', // Portugal
|
||||
'RO', // Romania
|
||||
'SE', // Sweden
|
||||
'SI', // Slovenia
|
||||
'SK', // Slovakia
|
||||
];
|
||||
|
||||
/** EU TAXES */
|
||||
|
||||
|
||||
/** US TAXES */
|
||||
/** US TAXES */
|
||||
|
||||
public string $tax_name1 = '';
|
||||
public float $tax_rate1 = 0;
|
||||
|
||||
public string $tax_name2 = '';
|
||||
public float $tax_rate2 = 0;
|
||||
|
||||
public string $tax_name3 = '';
|
||||
public float $tax_rate3 = 0;
|
||||
|
||||
protected ?Client $client;
|
||||
|
||||
protected ?Response $tax_data;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function init(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setClient(Client $client): self
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTaxData(Response $tax_data): self
|
||||
{
|
||||
$this->tax_data = $tax_data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function tax($product_tax_type): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxByType($product_tax_type): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxReduced(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxExempt(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxDigital(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxService(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxShipping(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxPhysical(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function default(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function override(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function calculateRates(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?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;
|
||||
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
|
||||
/**
|
||||
* ClientTaxData
|
||||
*
|
||||
* Definition for the client tax data
|
||||
*/
|
||||
class ClientTaxData
|
||||
{
|
||||
public int $updated_at;
|
||||
|
||||
public function __construct(public Response $origin, public Response $destination)
|
||||
{
|
||||
}
|
||||
}
|
233
app/DataMapper/Tax/DE/Rule.php
Normal file
233
app/DataMapper/Tax/DE/Rule.php
Normal file
@ -0,0 +1,233 @@
|
||||
<?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\DE;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Support\Str;
|
||||
use App\DataMapper\Tax\BaseRule;
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
|
||||
class Rule extends BaseRule implements RuleInterface
|
||||
{
|
||||
public string $vendor_country_code = 'DE';
|
||||
|
||||
public string $client_country_code = 'DE';
|
||||
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
public bool $foreign_business_tax_exempt = true;
|
||||
|
||||
public bool $foreign_consumer_tax_exempt = true;
|
||||
|
||||
public string $tax_name1 = '';
|
||||
|
||||
public float $tax_rate1 = 0;
|
||||
|
||||
public string $tax_name2 = '';
|
||||
|
||||
public float $tax_rate2 = 0;
|
||||
|
||||
public string $tax_name3 = '';
|
||||
|
||||
public float $tax_rate3 = 0;
|
||||
|
||||
public float $vat_rate = 0;
|
||||
|
||||
public float $reduced_vat_rate = 0;
|
||||
|
||||
protected ?Client $client;
|
||||
|
||||
protected ?Response $tax_data;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function init(): self
|
||||
{
|
||||
$this->client_country_code = $this->client->shipping_country ? $this->client->shipping_country->iso_3166_2 : $this->client->country->iso_3166_2;
|
||||
$this->calculateRates();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setClient(Client $client): self
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTaxData(Response $tax_data): self
|
||||
{
|
||||
$this->tax_data = $tax_data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
//need to add logic here to capture if
|
||||
public function tax($type): self
|
||||
{
|
||||
|
||||
|
||||
if ($this->client->is_tax_exempt) {
|
||||
return $this->taxExempt();
|
||||
} elseif ($this->client->company->tax_data->regions->EU->tax_all) {
|
||||
|
||||
$this->tax_rate1 = $this->vat_rate;
|
||||
$this->tax_name1 = "MwSt.";
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($type)
|
||||
return $this->taxByType($type);
|
||||
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function taxByType($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->reduced_vat_rate;
|
||||
$this->tax_name1 = 'ermäßigte MwSt.';
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public function override(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function calculateRates(): self
|
||||
{
|
||||
|
||||
if ($this->client->is_tax_exempt) {
|
||||
$this->vat_rate = 0;
|
||||
$this->reduced_vat_rate = 0;
|
||||
}
|
||||
elseif($this->client_country_code != $this->vendor_country_code && in_array($this->client_country_code, $this->eu_country_codes) && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt)
|
||||
{
|
||||
$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->foreign_consumer_tax_exempt || $this->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->client->has_valid_vat_number) //eu country / no valid vat
|
||||
{
|
||||
if(($this->vendor_country_code != $this->client_country_code) && $this->client->company->tax_data->regions->EU->has_sales_above_threshold)
|
||||
{
|
||||
$this->vat_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->vat_rate;
|
||||
$this->reduced_vat_rate = $this->client->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->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->vat_rate;
|
||||
$this->reduced_vat_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_vat_rate;
|
||||
// nlog("same eu country with");
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->vat_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->vat_rate;
|
||||
$this->reduced_vat_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_vat_rate;
|
||||
// nlog("default tax");
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -11,7 +11,36 @@
|
||||
|
||||
namespace App\DataMapper\Tax;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
|
||||
interface RuleInterface
|
||||
{
|
||||
public function run();
|
||||
public function init();
|
||||
|
||||
public function tax(mixed $type);
|
||||
|
||||
public function taxByType($type);
|
||||
|
||||
public function taxExempt();
|
||||
|
||||
public function taxDigital();
|
||||
|
||||
public function taxService();
|
||||
|
||||
public function taxShipping();
|
||||
|
||||
public function taxPhysical();
|
||||
|
||||
public function taxReduced();
|
||||
|
||||
public function default();
|
||||
|
||||
public function override();
|
||||
|
||||
public function setClient(Client $client);
|
||||
|
||||
public function setTaxData(Response $tax_data);
|
||||
|
||||
public function calculateRates();
|
||||
}
|
@ -18,11 +18,14 @@ use App\DataMapper\Tax\ZipTax\Response;
|
||||
*
|
||||
* Definition for the invoice tax data structure
|
||||
*/
|
||||
class InvoiceTaxData
|
||||
class TaxData
|
||||
{
|
||||
public int $updated_at;
|
||||
|
||||
public function __construct(public Response $origin)
|
||||
{
|
||||
foreach($origin as $key => $value) {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
}
|
||||
}
|
316
app/DataMapper/Tax/TaxModel.php
Normal file
316
app/DataMapper/Tax/TaxModel.php
Normal 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_subregions = false;
|
||||
$this->usSubRegions();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function euRegion(): self
|
||||
{
|
||||
|
||||
$this->regions->EU->has_sales_above_threshold = false;
|
||||
$this->regions->EU->tax_all_subregions = 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;
|
||||
|
||||
}
|
||||
|
||||
}
|
161
app/DataMapper/Tax/US/Rule.php
Normal file
161
app/DataMapper/Tax/US/Rule.php
Normal file
@ -0,0 +1,161 @@
|
||||
<?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\US;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Product;
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
|
||||
class Rule implements RuleInterface
|
||||
{
|
||||
|
||||
public string $tax_name1 = '';
|
||||
public float $tax_rate1 = 0;
|
||||
|
||||
public string $tax_name2 = '';
|
||||
public float $tax_rate2 = 0;
|
||||
|
||||
public string $tax_name3 = '';
|
||||
public float $tax_rate3 = 0;
|
||||
|
||||
public ?Client $client;
|
||||
|
||||
public ?Response $tax_data;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function override()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTaxData(Response $tax_data): self
|
||||
{
|
||||
$this->tax_data = $tax_data;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setClient(Client $client):self
|
||||
{
|
||||
$this->client = $client;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function tax($type): self
|
||||
{
|
||||
|
||||
if ($this->client->is_tax_exempt) {
|
||||
return $this->taxExempt();
|
||||
}
|
||||
else if($this->client->company->tax_data->regions->US->tax_all){
|
||||
|
||||
$this->tax_rate1 = $this->tax_data->taxSales * 100;
|
||||
$this->tax_name1 = "{$this->tax_data->geoState} Sales Tax";
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
if($type)
|
||||
return $this->taxByType($type);
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function taxByType($product_tax_type): self
|
||||
{
|
||||
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 taxExempt(): self
|
||||
{
|
||||
$this->tax_name1 = '';
|
||||
$this->tax_rate1 = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxDigital(): self
|
||||
{
|
||||
$this->default();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxService(): self
|
||||
{
|
||||
if($this->tax_data->txbService == 'Y')
|
||||
$this->default();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxShipping(): self
|
||||
{
|
||||
if($this->tax_data->txbFreight == 'Y')
|
||||
$this->default();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxPhysical(): self
|
||||
{
|
||||
$this->default();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function default(): self
|
||||
{
|
||||
|
||||
$this->tax_rate1 = $this->tax_data->taxSales * 100;
|
||||
$this->tax_name1 = "{$this->tax_data->geoState} Sales Tax";
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxReduced(): self
|
||||
{
|
||||
$this->default();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function init(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function calculateRates(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -18,8 +18,7 @@ class Response
|
||||
public int $rCode = 100;
|
||||
|
||||
/**
|
||||
* ["results" => [
|
||||
* [
|
||||
* [
|
||||
* "geoPostalCode" => "92582",
|
||||
* "geoCity" => "SAN JACINTO",
|
||||
* "geoCounty" => "RIVERSIDE",
|
||||
@ -54,13 +53,56 @@ class Response
|
||||
* "district5SalesTax" => 0,
|
||||
* "district5UseTax" => 0,
|
||||
* "originDestination" => "D",
|
||||
* ],
|
||||
* ]
|
||||
*
|
||||
* ];
|
||||
*
|
||||
* @var mixed[]
|
||||
*
|
||||
*/
|
||||
public array $results = [];
|
||||
public string $seller_region = "";
|
||||
//US
|
||||
|
||||
public string $geoPostalCode = "";
|
||||
public string $geoCity = "";
|
||||
public string $geoCounty = "";
|
||||
public string $geoState = "";
|
||||
public float $taxSales = 0;
|
||||
public float $taxUse = 0;
|
||||
public string $txbService = ""; // N = No, Y = Yes
|
||||
public string $txbFreight = ""; // N = No, Y = Yes
|
||||
public float $stateSalesTax = 0;
|
||||
public float $stateUseTax = 0;
|
||||
public float $citySalesTax = 0;
|
||||
public float $cityUseTax = 0;
|
||||
public string $cityTaxCode = "";
|
||||
public float $countySalesTax = 0;
|
||||
public float $countyUseTax = 0;
|
||||
public string $countyTaxCode = "";
|
||||
public float $districtSalesTax = 0;
|
||||
public float $districtUseTax = 0;
|
||||
public string $district1Code = "";
|
||||
public float $district1SalesTax = 0;
|
||||
public float $district1UseTax = 0;
|
||||
public string $district2Code = "";
|
||||
public float $district2SalesTax = 0;
|
||||
public float $district2UseTax = 0;
|
||||
public string $district3Code = "";
|
||||
public float $district3SalesTax = 0;
|
||||
public float $district3UseTax = 0;
|
||||
public string $district4Code = "";
|
||||
public float $district4SalesTax = 0;
|
||||
public float $district4UseTax = 0;
|
||||
public string $district5Code = "";
|
||||
public float $district5SalesTax = 0;
|
||||
public float $district5UseTax = 0;
|
||||
public string $originDestination = "";
|
||||
|
||||
public function __construct($data)
|
||||
{
|
||||
|
||||
foreach($data as $key => $value){
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,96 +0,0 @@
|
||||
<?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\de;
|
||||
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
|
||||
class Rule 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 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;
|
||||
|
||||
public function run()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
220
app/DataMapper/Tax/tax_model.yaml
Normal file
220
app/DataMapper/Tax/tax_model.yaml
Normal file
@ -0,0 +1,220 @@
|
||||
region:
|
||||
US:
|
||||
tax_all_subregions: false
|
||||
seller_subregion: CA
|
||||
has_sales_above_threshold: false
|
||||
subregions:
|
||||
AL:
|
||||
apply_tax: false
|
||||
AK:
|
||||
apply_tax: false
|
||||
AZ:
|
||||
apply_tax: false
|
||||
AR:
|
||||
apply_tax: false
|
||||
CA:
|
||||
apply_tax: false
|
||||
CO:
|
||||
apply_tax: false
|
||||
CT:
|
||||
apply_tax: false
|
||||
DE:
|
||||
apply_tax: false
|
||||
FL:
|
||||
apply_tax: false
|
||||
GA:
|
||||
apply_tax: false
|
||||
HI:
|
||||
apply_tax: false
|
||||
ID:
|
||||
apply_tax: false
|
||||
IL:
|
||||
apply_tax: false
|
||||
IN:
|
||||
apply_tax: false
|
||||
IA:
|
||||
apply_tax: false
|
||||
KS:
|
||||
apply_tax: false
|
||||
KY:
|
||||
apply_tax: false
|
||||
LA:
|
||||
apply_tax: false
|
||||
ME:
|
||||
apply_tax: false
|
||||
MD:
|
||||
apply_tax: false
|
||||
MA:
|
||||
apply_tax: false
|
||||
MI:
|
||||
apply_tax: false
|
||||
MN:
|
||||
apply_tax: false
|
||||
MS:
|
||||
apply_tax: false
|
||||
MO:
|
||||
apply_tax: false
|
||||
MT:
|
||||
apply_tax: false
|
||||
NE:
|
||||
apply_tax: false
|
||||
NV:
|
||||
apply_tax: false
|
||||
NH:
|
||||
apply_tax: false
|
||||
NJ:
|
||||
apply_tax: false
|
||||
NM:
|
||||
apply_tax: false
|
||||
NY:
|
||||
apply_tax: false
|
||||
NC:
|
||||
apply_tax: false
|
||||
ND:
|
||||
apply_tax: false
|
||||
OH:
|
||||
apply_tax: false
|
||||
OK:
|
||||
apply_tax: false
|
||||
OR:
|
||||
apply_tax: false
|
||||
PA:
|
||||
apply_tax: false
|
||||
RI:
|
||||
apply_tax: false
|
||||
SC:
|
||||
apply_tax: false
|
||||
SD:
|
||||
apply_tax: false
|
||||
TN:
|
||||
apply_tax: false
|
||||
TX:
|
||||
apply_tax: false
|
||||
UT:
|
||||
apply_tax: false
|
||||
VT:
|
||||
apply_tax: false
|
||||
VA:
|
||||
apply_tax: false
|
||||
WA:
|
||||
apply_tax: false
|
||||
WV:
|
||||
apply_tax: false
|
||||
WI:
|
||||
apply_tax: false
|
||||
WY:
|
||||
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_tax: false
|
||||
BE:
|
||||
vat: 21
|
||||
reduced_vat: 6
|
||||
apply_tax: false
|
||||
BG:
|
||||
vat: 20
|
||||
reduced_vat: 9
|
||||
apply_tax: false
|
||||
CY:
|
||||
vat: 19
|
||||
reduced_vat: 9
|
||||
apply_tax: false
|
||||
CZ:
|
||||
vat: 21
|
||||
reduced_vat: 15
|
||||
apply_tax: false
|
||||
DE:
|
||||
vat: 19
|
||||
reduced_vat: 7
|
||||
apply_tax: false
|
||||
DK:
|
||||
vat: 25
|
||||
reduced_vat: 0
|
||||
apply_tax: false
|
||||
EE:
|
||||
vat: 20
|
||||
reduced_vat: 9
|
||||
apply_tax: false
|
||||
ES:
|
||||
vat: 21
|
||||
reduced_vat: 10
|
||||
apply_tax: false
|
||||
FI:
|
||||
vat: 24
|
||||
reduced_vat: 14
|
||||
apply_tax: false
|
||||
FR:
|
||||
vat: 20
|
||||
reduced_vat: 5.5
|
||||
apply_tax: false
|
||||
GB:
|
||||
vat: 20
|
||||
reduced_vat: 0
|
||||
apply_tax: false
|
||||
GR:
|
||||
vat: 24
|
||||
reduced_vat: 13
|
||||
apply_tax: false
|
||||
HR:
|
||||
vat: 25
|
||||
reduced_vat: 5
|
||||
apply_tax: false
|
||||
HU:
|
||||
vat: 27
|
||||
reduced_vat: 5
|
||||
apply_tax: false
|
||||
IE:
|
||||
vat: 23
|
||||
reduced_vat: 0
|
||||
apply_tax: false
|
||||
IT:
|
||||
vat: 22
|
||||
reduced_vat: 10
|
||||
apply_tax: false
|
||||
LT:
|
||||
vat: 21
|
||||
reduced_vat: 9
|
||||
apply_tax: false
|
||||
LU:
|
||||
vat: 17
|
||||
reduced_vat: 3
|
||||
apply_tax: false
|
||||
LV:
|
||||
vat: 21
|
||||
reduced_vat: 12
|
||||
apply_tax: false
|
||||
MT:
|
||||
vat: 18
|
||||
reduced_vat: 5
|
||||
apply_tax: false
|
||||
NL:
|
||||
vat: 21
|
||||
reduced_vat: 9
|
||||
apply_tax: false
|
||||
PT:
|
||||
vat: 23
|
||||
reduced_vat: 6
|
||||
apply_tax: false
|
||||
RO:
|
||||
vat: 19
|
||||
reduced_vat: 5
|
||||
apply_tax: false
|
||||
SE:
|
||||
vat: 25
|
||||
reduced_vat: 12
|
||||
apply_tax: false
|
||||
SI:
|
||||
vat: 22
|
||||
reduced_vat: 9.5
|
||||
apply_tax: false
|
||||
SK:
|
||||
vat: 20
|
||||
reduced_vat: 10
|
||||
apply_tax: false
|
@ -1,70 +0,0 @@
|
||||
<?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\us;
|
||||
|
||||
class Rule
|
||||
{
|
||||
|
||||
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
|
||||
|
||||
}
|
@ -35,7 +35,8 @@ class ProductFactory
|
||||
$product->custom_value3 = '';
|
||||
$product->custom_value4 = '';
|
||||
$product->is_deleted = 0;
|
||||
|
||||
$product->tax_id = 1;
|
||||
|
||||
return $product;
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,13 @@
|
||||
|
||||
namespace App\Helpers\Invoice;
|
||||
|
||||
use App\DataMapper\BaseSettings;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\DataMapper\BaseSettings;
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
use App\Utils\Traits\NumberFormatter;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
|
||||
class InvoiceItemSum
|
||||
{
|
||||
@ -22,6 +25,38 @@ class InvoiceItemSum
|
||||
use Discounter;
|
||||
use Taxer;
|
||||
|
||||
private array $tax_jurisdictions = [
|
||||
'AT', // Austria
|
||||
'BE', // Belgium
|
||||
'BG', // Bulgaria
|
||||
'CY', // Cyprus
|
||||
'CZ', // Czech Republic
|
||||
'DE', // Germany
|
||||
'DK', // Denmark
|
||||
'EE', // Estonia
|
||||
'ES', // Spain
|
||||
'FI', // Finland
|
||||
'FR', // France
|
||||
'GR', // Greece
|
||||
'HR', // Croatia
|
||||
'HU', // Hungary
|
||||
'IE', // Ireland
|
||||
'IT', // Italy
|
||||
'LT', // Lithuania
|
||||
'LU', // Luxembourg
|
||||
'LV', // Latvia
|
||||
'MT', // Malta
|
||||
'NL', // Netherlands
|
||||
'PL', // Poland
|
||||
'PT', // Portugal
|
||||
'RO', // Romania
|
||||
'SE', // Sweden
|
||||
'SI', // Slovenia
|
||||
'SK', // Slovakia
|
||||
|
||||
'US', //USA
|
||||
];
|
||||
|
||||
protected $invoice;
|
||||
|
||||
private $items;
|
||||
@ -48,6 +83,12 @@ class InvoiceItemSum
|
||||
|
||||
private $tax_collection;
|
||||
|
||||
private ?Client $client;
|
||||
|
||||
private bool $calc_tax = false;
|
||||
|
||||
private RuleInterface $rule;
|
||||
|
||||
public function __construct($invoice)
|
||||
{
|
||||
$this->tax_collection = collect([]);
|
||||
@ -56,6 +97,8 @@ class InvoiceItemSum
|
||||
|
||||
if ($this->invoice->client) {
|
||||
$this->currency = $this->invoice->client->currency();
|
||||
$this->client = $this->invoice->client;
|
||||
$this->shouldCalculateTax();
|
||||
} else {
|
||||
$this->currency = $this->invoice->vendor->currency();
|
||||
}
|
||||
@ -89,6 +132,33 @@ class InvoiceItemSum
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function shouldCalculateTax(): self
|
||||
{
|
||||
if (!$this->invoice->company->calculate_taxes) {
|
||||
$this->calc_tax = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
//should we be filtering by client country here? do we need to reflect at the company <=> client level?
|
||||
if (in_array($this->client->country->iso_3166_2, $this->tax_jurisdictions)) { //only calculate for supported tax jurisdictions
|
||||
$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)
|
||||
->init();
|
||||
|
||||
$this->calc_tax = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function push()
|
||||
{
|
||||
$this->sub_total += $this->getLineTotal();
|
||||
@ -122,8 +192,33 @@ class InvoiceItemSum
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to calculate taxes based on the clients location
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function calcTaxesAutomatically(): self
|
||||
{
|
||||
$this->rule->tax($this->item->tax_id ?? null);
|
||||
|
||||
$this->item->tax_name1 = $this->rule->tax_name1;
|
||||
$this->item->tax_rate1 = $this->rule->tax_rate1;
|
||||
|
||||
$this->item->tax_name2 = $this->rule->tax_name2;
|
||||
$this->item->tax_rate2 = $this->rule->tax_rate2;
|
||||
|
||||
$this->item->tax_name3 = $this->rule->tax_name3;
|
||||
$this->item->tax_rate3 = $this->rule->tax_rate3;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function calcTaxes()
|
||||
{
|
||||
if ($this->calc_tax) {
|
||||
$this->calcTaxesAutomatically();
|
||||
}
|
||||
|
||||
$item_tax = 0;
|
||||
|
||||
$amount = $this->item->line_total - ($this->item->line_total * ($this->invoice->discount / 100));
|
||||
@ -131,7 +226,6 @@ class InvoiceItemSum
|
||||
|
||||
$item_tax += $item_tax_rate1_total;
|
||||
|
||||
// if($item_tax_rate1_total != 0)
|
||||
if (strlen($this->item->tax_name1) > 1) {
|
||||
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
|
||||
}
|
||||
@ -155,7 +249,7 @@ class InvoiceItemSum
|
||||
$this->setTotalTaxes($this->formatValue($item_tax, $this->currency->precision));
|
||||
|
||||
$this->item->gross_line_total = $this->getLineTotal() + $item_tax;
|
||||
|
||||
|
||||
$this->item->tax_amount = $item_tax;
|
||||
|
||||
return $this;
|
||||
|
@ -11,16 +11,17 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\Account\CreateAccountRequest;
|
||||
use App\Http\Requests\Account\UpdateAccountRequest;
|
||||
use App\Jobs\Account\CreateAccount;
|
||||
use App\Models\Account;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Utils\TruthSource;
|
||||
use App\Models\CompanyUser;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Jobs\Account\CreateAccount;
|
||||
use App\Transformers\AccountTransformer;
|
||||
use App\Transformers\CompanyUserTransformer;
|
||||
use App\Utils\TruthSource;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Http\Response;
|
||||
use App\Http\Requests\Account\CreateAccountRequest;
|
||||
use App\Http\Requests\Account\UpdateAccountRequest;
|
||||
|
||||
class AccountController extends BaseController
|
||||
{
|
||||
@ -146,8 +147,10 @@ class AccountController extends BaseController
|
||||
if (! ($account instanceof Account)) {
|
||||
return $account;
|
||||
}
|
||||
|
||||
MultiDB::findAndSetDbByAccountKey($account->key);
|
||||
|
||||
$cu = CompanyUser::where('user_id', auth()->user()->id);
|
||||
$cu = CompanyUser::where('user_id', $account->users()->first()->id);
|
||||
|
||||
$company_user = $cu->first();
|
||||
|
||||
|
@ -38,6 +38,8 @@ class HostedMigrationController extends Controller
|
||||
$account->hosted_company_count = 10;
|
||||
$account->save();
|
||||
|
||||
MultiDB::findAndSetDbByAccountKey($account->key);
|
||||
|
||||
$company = $account->companies->first();
|
||||
|
||||
$company_token = CompanyToken::where('user_id', auth()->user()->id)
|
||||
|
@ -144,7 +144,7 @@ class PreviewController extends BaseController
|
||||
$maker
|
||||
->design($design)
|
||||
->build();
|
||||
|
||||
|
||||
if (request()->query('html') == 'true') {
|
||||
return $maker->getCompiledHTML();
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class StorePrePaymentRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'notes' => 'required|bail|',
|
||||
'amount' => 'required|bail|gte:minimum_amount',
|
||||
'amount' => 'required|bail|gte:minimum_amount|numeric',
|
||||
'minimum_amount' => '',
|
||||
];
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Http\Requests\Invoice;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
|
||||
class UploadInvoiceRequest extends Request
|
||||
{
|
||||
@ -46,5 +47,24 @@ class UploadInvoiceRequest extends Request
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
|
||||
//tests to see if upload via binary data works.
|
||||
|
||||
// if(request()->getContent())
|
||||
// {
|
||||
// // $file = new UploadedFile(request()->getContent(), request()->header('filename'));
|
||||
// $file = new UploadedFile(request()->getContent(), 'something.png');
|
||||
// // request()->files->set('documents', $file);
|
||||
|
||||
// $this->files->add(['file' => $file]);
|
||||
|
||||
// // Merge it in request also (As I found this is not needed in every case)
|
||||
// $this->merge(['file' => $file]);
|
||||
|
||||
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -115,9 +115,9 @@ class AdjustProductInventory implements ShouldQueue
|
||||
$p->in_stock_quantity -= $i->quantity;
|
||||
|
||||
$p->saveQuietly();
|
||||
nlog($p->stock_notification_threshold);
|
||||
nlog($p->in_stock_quantity);
|
||||
nlog($p->stock_notification_threshold);
|
||||
nlog("threshold ".$p->stock_notification_threshold);
|
||||
nlog("stock q".$p->in_stock_quantity);
|
||||
nlog("p stock not".$p->stock_notification_threshold);
|
||||
|
||||
if ($this->company->stock_notification && $p->stock_notification && $p->stock_notification_threshold && $p->in_stock_quantity <= $p->stock_notification_threshold) {
|
||||
$this->notifyStockLevels($p, 'product');
|
||||
@ -131,7 +131,7 @@ class AdjustProductInventory implements ShouldQueue
|
||||
private function existingInventoryAdjustment()
|
||||
{
|
||||
|
||||
collect($this->invoice->line_items)->filter(function ($item) {
|
||||
collect($this->old_invoice)->filter(function ($item) {
|
||||
return $item->type_id == '1';
|
||||
})->each(function ($i) {
|
||||
$p = Product::where('product_key', $i->product_key)->where('company_id', $this->company->id)->first();
|
||||
|
@ -142,6 +142,26 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -35,6 +35,11 @@ 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
|
||||
* @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
|
||||
|
@ -78,6 +78,11 @@ 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
|
||||
* @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
|
||||
|
@ -221,6 +221,93 @@ 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 int $is_tax_exempt
|
||||
* @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
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Client whereIsTaxExempt($value)
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -138,6 +138,31 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -419,6 +419,226 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -95,6 +95,11 @@ 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
|
||||
* @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
|
||||
|
@ -76,6 +76,21 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -206,6 +206,41 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -133,6 +133,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\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
|
||||
* @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
|
||||
|
@ -31,6 +31,11 @@ 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
|
||||
* @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
|
||||
|
@ -60,6 +60,16 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -232,6 +232,51 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -147,6 +147,31 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -101,6 +101,11 @@ use League\CommonMark\CommonMarkConverter;
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Document> $documents
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|Product whereTaxId($value)
|
||||
* @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
|
||||
* @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
|
||||
@ -109,12 +114,13 @@ class Product extends BaseModel
|
||||
use SoftDeletes;
|
||||
use Filterable;
|
||||
|
||||
|
||||
public const PRODUCT_TYPE_PHYSICAL = 1;
|
||||
public const PRODUCT_TYPE_SERVICE = 2;
|
||||
public const PRODUCT_TYPE_DIGITAL = 3;
|
||||
public const PRODUCT_TYPE_FREIGHT = 4;
|
||||
public const PRODUCT_TAX_EXEMPT = 5;
|
||||
public const PRODUCT_TYPE_SHIPPING = 4;
|
||||
public const PRODUCT_TYPE_EXEMPT = 5;
|
||||
public const PRODUCT_TYPE_REDUCED_TAX = 6;
|
||||
public const PRODUCT_TYPE_OVERRIDE_TAX = 7;
|
||||
|
||||
protected $fillable = [
|
||||
'custom_value1',
|
||||
|
@ -78,6 +78,16 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -31,6 +31,11 @@ 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
|
||||
* @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
|
||||
|
@ -198,6 +198,36 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -193,6 +193,26 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -142,6 +142,11 @@ 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
|
||||
* @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
|
||||
|
@ -194,6 +194,31 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -186,6 +186,31 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -94,6 +94,11 @@ 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
|
||||
* @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
|
||||
|
@ -160,6 +160,41 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -116,6 +116,26 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -116,6 +116,16 @@ 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
|
||||
* @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
|
||||
* @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
|
||||
|
@ -1,153 +0,0 @@
|
||||
<?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\Services\Tax;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Support\Str;
|
||||
use App\DataMapper\Tax\de\Rule;
|
||||
use App\Services\Tax\VatNumberCheck;
|
||||
class ProcessRule
|
||||
{
|
||||
public Rule $rule;
|
||||
|
||||
private string $vendor_country_code;
|
||||
|
||||
private string $client_country_code;
|
||||
|
||||
private bool $valid_vat_number = false;
|
||||
|
||||
private float $vat_rate = 0.0;
|
||||
|
||||
private float $vat_reduced_rate = 0.0;
|
||||
|
||||
private array $eu_country_codes = [
|
||||
'AT', // Austria
|
||||
'BE', // Belgium
|
||||
'BG', // Bulgaria
|
||||
'CY', // Cyprus
|
||||
'CZ', // Czech Republic
|
||||
'DE', // Germany
|
||||
'DK', // Denmark
|
||||
'EE', // Estonia
|
||||
'ES', // Spain
|
||||
'FI', // Finland
|
||||
'FR', // France
|
||||
'GR', // Greece
|
||||
'HR', // Croatia
|
||||
'HU', // Hungary
|
||||
'IE', // Ireland
|
||||
'IT', // Italy
|
||||
'LT', // Lithuania
|
||||
'LU', // Luxembourg
|
||||
'LV', // Latvia
|
||||
'MT', // Malta
|
||||
'NL', // Netherlands
|
||||
'PL', // Poland
|
||||
'PT', // Portugal
|
||||
'RO', // Romania
|
||||
'SE', // Sweden
|
||||
'SI', // Slovenia
|
||||
'SK', // Slovakia
|
||||
];
|
||||
|
||||
|
||||
|
||||
public function __construct(protected Company $company, protected Client $client)
|
||||
{
|
||||
}
|
||||
|
||||
/* need to have a setting that allows a user to define their annual turnover, or whether they have breached their thresholds */
|
||||
public function run()
|
||||
{
|
||||
$this->setUp()
|
||||
->validateVat()
|
||||
->calculateVatRates();
|
||||
}
|
||||
|
||||
public function hasValidVatNumber(): bool
|
||||
{
|
||||
return $this->valid_vat_number;
|
||||
}
|
||||
|
||||
public function getVatRate(): float
|
||||
{
|
||||
return $this->vat_rate;
|
||||
}
|
||||
|
||||
public function getVatReducedRate(): float
|
||||
{
|
||||
return $this->vat_reduced_rate;
|
||||
}
|
||||
|
||||
public function getVendorCountryCode(): string
|
||||
{
|
||||
return $this->vendor_country_code;
|
||||
}
|
||||
|
||||
public function getClientCountryCode(): string
|
||||
{
|
||||
return $this->client_country_code;
|
||||
}
|
||||
|
||||
private function setUp(): self
|
||||
{
|
||||
$this->vendor_country_code = Str::lower($this->company->country()->iso_3166_2);
|
||||
|
||||
$this->client_country_code = $this->client->shipping_country ? Str::lower($this->client->shipping_country->iso_3166_2) : Str::lower($this->client->country->iso_3166_2);
|
||||
|
||||
$class = "App\\DataMapper\\Tax\\".$this->vendor_country_code."\\Rule";
|
||||
|
||||
$this->rule = new $class();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function validateVat(): self
|
||||
{
|
||||
$vat_check = (new VatNumberCheck($this->client->vat_number, $this->client_country_code))->run();
|
||||
|
||||
$this->valid_vat_number = $vat_check->isValid();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function calculateVatRates(): self
|
||||
{
|
||||
|
||||
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->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)) {
|
||||
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->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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
}
|
189
app/Services/Tax/Providers/TaxProvider.php
Normal file
189
app/Services/Tax/Providers/TaxProvider.php
Normal file
@ -0,0 +1,189 @@
|
||||
<?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\Services\Tax\Providers;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Services\Tax\Providers\EuTax;
|
||||
|
||||
class TaxProvider
|
||||
{
|
||||
|
||||
public array $eu_countries = [
|
||||
"AT",
|
||||
"BE",
|
||||
"BG",
|
||||
"HR",
|
||||
"CY",
|
||||
"CZ",
|
||||
"DK",
|
||||
"EE",
|
||||
"FI",
|
||||
"FR",
|
||||
"DE",
|
||||
"GR",
|
||||
"HU",
|
||||
"IE",
|
||||
"IT",
|
||||
"LV",
|
||||
"LT",
|
||||
"LU",
|
||||
"MT",
|
||||
"NL",
|
||||
"PL",
|
||||
"PT",
|
||||
"RO",
|
||||
"SK",
|
||||
"SI",
|
||||
"ES",
|
||||
"SE"
|
||||
];
|
||||
|
||||
private string $provider = ZipTax::class;
|
||||
|
||||
private mixed $api_credentials;
|
||||
|
||||
public function __construct(protected Company $company, protected Client $client)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function updateCompanyTaxData(): self
|
||||
{
|
||||
$this->configureProvider($this->provider); //hard coded for now to one provider, but we'll be able to swap these out later
|
||||
|
||||
$company_details = [
|
||||
'address1' => $this->company->settings->address1,
|
||||
'address2' => $this->company->settings->address2,
|
||||
'city' => $this->company->settings->city,
|
||||
'state' => $this->company->settings->state,
|
||||
'postal_code' => $this->company->settings->postal_code,
|
||||
'country_id' => $this->company->settings->country_id,
|
||||
];
|
||||
|
||||
$tax_provider = new $this->provider($company_details);
|
||||
|
||||
$tax_provider->setApiCredentials($this->api_credentials);
|
||||
|
||||
$tax_data = $tax_provider->run();
|
||||
|
||||
$this->company->tax_data = $tax_data;
|
||||
|
||||
$this->company->save();
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function updateClientTaxData(): self
|
||||
{
|
||||
$this->configureProvider($this->provider); //hard coded for now to one provider, but we'll be able to swap these out later
|
||||
|
||||
$billing_details =[
|
||||
'address1' => $this->client->address1,
|
||||
'address2' => $this->client->address2,
|
||||
'city' => $this->client->city,
|
||||
'state' => $this->client->state,
|
||||
'postal_code' => $this->client->postal_code,
|
||||
'country_id' => $this->client->country_id,
|
||||
];
|
||||
|
||||
$shipping_details =[
|
||||
'address1' => $this->client->shipping_address1,
|
||||
'address2' => $this->client->shipping_address2,
|
||||
'city' => $this->client->shipping_city,
|
||||
'state' => $this->client->shipping_state,
|
||||
'postal_code' => $this->client->shipping_postal_code,
|
||||
'country_id' => $this->client->shipping_country_id,
|
||||
];
|
||||
|
||||
|
||||
$tax_provider = new $this->provider();
|
||||
|
||||
$tax_provider->setApiCredentials($this->api_credentials);
|
||||
|
||||
$tax_data = $tax_provider->run();
|
||||
|
||||
$this->company->tax_data = $tax_data;
|
||||
|
||||
$this->company->save();
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
private function configureProvider(?string $provider): self
|
||||
{
|
||||
|
||||
match($this->client->country->iso_3166_2){
|
||||
'US' => $this->configureZipTax(),
|
||||
"AT" => $this->configureEuTax(),
|
||||
"BE" => $this->configureEuTax(),
|
||||
"BG" => $this->configureEuTax(),
|
||||
"HR" => $this->configureEuTax(),
|
||||
"CY" => $this->configureEuTax(),
|
||||
"CZ" => $this->configureEuTax(),
|
||||
"DK" => $this->configureEuTax(),
|
||||
"EE" => $this->configureEuTax(),
|
||||
"FI" => $this->configureEuTax(),
|
||||
"FR" => $this->configureEuTax(),
|
||||
"DE" => $this->configureEuTax(),
|
||||
"GR" => $this->configureEuTax(),
|
||||
"HU" => $this->configureEuTax(),
|
||||
"IE" => $this->configureEuTax(),
|
||||
"IT" => $this->configureEuTax(),
|
||||
"LV" => $this->configureEuTax(),
|
||||
"LT" => $this->configureEuTax(),
|
||||
"LU" => $this->configureEuTax(),
|
||||
"MT" => $this->configureEuTax(),
|
||||
"NL" => $this->configureEuTax(),
|
||||
"PL" => $this->configureEuTax(),
|
||||
"PT" => $this->configureEuTax(),
|
||||
"RO" => $this->configureEuTax(),
|
||||
"SK" => $this->configureEuTax(),
|
||||
"SI" => $this->configureEuTax(),
|
||||
"ES" => $this->configureEuTax(),
|
||||
"SE" => $this->configureEuTax(),
|
||||
default => $this->noTaxRegionDefined(),
|
||||
};
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
private function configureEuTax(): self
|
||||
{
|
||||
$this->provider = EuTax::class;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function noTaxRegionDefined(): self
|
||||
{
|
||||
throw new \Exception("No tax region defined for this country");
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function configureZipTax(): self
|
||||
{
|
||||
|
||||
$this->provider = ZipTax::class;
|
||||
|
||||
$this->api_credentials = config('services.tax.zip_tax.key');
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -9,20 +9,12 @@
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataMapper\Tax;
|
||||
namespace App\Services\Tax\Providers;
|
||||
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
|
||||
/**
|
||||
* CompanyTaxData
|
||||
*
|
||||
* Definition for the company tax data structure
|
||||
*/
|
||||
class CompanyTaxData
|
||||
interface TaxProviderInterface
|
||||
{
|
||||
public int $updated_at;
|
||||
|
||||
public function __construct(public Response $origin)
|
||||
{
|
||||
}
|
||||
public function run();
|
||||
|
||||
public function setApiCredentials(mixed $credentials);
|
||||
|
||||
}
|
@ -14,12 +14,14 @@ namespace App\Services\Tax\Providers;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class ZipTax
|
||||
class ZipTax implements TaxProviderInterface
|
||||
{
|
||||
|
||||
private string $endpoint = 'https://api.zip-tax.com/request/v40';
|
||||
|
||||
public function __construct(protected string $api_key, protected string $address, protected ?string $postal_code)
|
||||
private string $api_key = '';
|
||||
|
||||
public function __construct(protected array $address)
|
||||
{
|
||||
}
|
||||
|
||||
@ -43,6 +45,13 @@ class ZipTax
|
||||
|
||||
}
|
||||
|
||||
public function setApiCredentials($api_key): self
|
||||
{
|
||||
$this->api_key = $api_key;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* callApi
|
||||
*
|
||||
|
@ -13,6 +13,7 @@ namespace App\Services\Tax;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Services\Tax\Providers\ZipTax;
|
||||
|
||||
|
||||
class TaxService
|
||||
@ -22,4 +23,15 @@ class TaxService
|
||||
{
|
||||
}
|
||||
|
||||
private function validateVat(): self
|
||||
{
|
||||
$client_country_code = $this->client->shipping_country ? $this->client->shipping_country->iso_3166_2 : $this->client->country->iso_3166_2;
|
||||
|
||||
$vat_check = (new VatNumberCheck($this->client->vat_number, $client_country_code))->run();
|
||||
|
||||
$this->client->has_valid_vat_number = $vat_check->isValid();
|
||||
$this->client->saveQuietly();
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -147,6 +147,9 @@ class ClientTransformer extends EntityTransformer
|
||||
'created_at' => (int) $client->created_at,
|
||||
'display_name' => $client->present()->name(),
|
||||
'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 ?: '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -194,6 +194,7 @@ class CompanyTransformer extends EntityTransformer
|
||||
'notify_vendor_when_paid' => (bool) $company->notify_vendor_when_paid,
|
||||
'invoice_task_hours' => (bool) $company->invoice_task_hours,
|
||||
'calculate_taxes' => (bool) $company->calculate_taxes,
|
||||
'tax_data' => $company->tax_data ?: '',
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -374,7 +374,6 @@ class HtmlEngine
|
||||
|
||||
$data['$user_iban'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'company1', $this->settings->custom_value1, $this->client) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'company1')];
|
||||
|
||||
|
||||
$data['$invoice.public_notes'] = ['value' => Helpers::processReservedKeywords(\nl2br($this->entity->public_notes ?: ''), $this->client) ?: '', 'label' => ctrans('texts.public_notes')];
|
||||
$data['$entity.public_notes'] = &$data['$invoice.public_notes'];
|
||||
$data['$public_notes'] = &$data['$invoice.public_notes'];
|
||||
|
@ -96,4 +96,9 @@ return [
|
||||
'redirect' => env('BITBUCKET_OAUTH_REDIRECT'),
|
||||
],
|
||||
|
||||
'tax' => [
|
||||
'zip_tax' => [
|
||||
'key' => env('ZIP_TAX_KEY', false),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
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();
|
||||
$table->dropColumn('tax_all_products');
|
||||
});
|
||||
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->unsignedInteger('tax_id')->nullable(); // the product tax constant
|
||||
});
|
||||
|
||||
Company::query()
|
||||
->cursor()
|
||||
->each(function ($company) {
|
||||
$company->tax_data = null;
|
||||
$company->save();
|
||||
});
|
||||
|
||||
Client::query()
|
||||
->cursor()
|
||||
->each(function ($client) {
|
||||
$client->tax_data = null;
|
||||
$client->save();
|
||||
});
|
||||
|
||||
Product::query()
|
||||
->cursor()
|
||||
->each(function ($product) {
|
||||
$product->tax_id = 1;
|
||||
$product->save();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
@ -2,4 +2,5 @@ parameters:
|
||||
level: 2
|
||||
paths:
|
||||
- app
|
||||
# - tests
|
||||
universalObjectCratesClasses:
|
||||
- App\DataMapper\Tax\RuleInterface
|
616
tests/Unit/Tax/EuTaxTest.php
Normal file
616
tests/Unit/Tax/EuTaxTest.php
Normal file
@ -0,0 +1,616 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace Tests\Unit\Tax;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @test App\Services\Tax\Providers\EuTax
|
||||
*/
|
||||
class EuTaxTest extends TestCase
|
||||
{
|
||||
use MockAccountData;
|
||||
use DatabaseTransactions;
|
||||
|
||||
protected function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
|
||||
$this->makeTestData();
|
||||
}
|
||||
|
||||
public function testInvoiceTaxCalcDetoBeNoVat()
|
||||
{
|
||||
$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,
|
||||
'tax_data' => $tax_data,
|
||||
'calculate_taxes' => true,
|
||||
]);
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 56,
|
||||
'shipping_country_id' => 56,
|
||||
'has_valid_vat_number' => false,
|
||||
]);
|
||||
|
||||
$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_rate1' => 0,
|
||||
'tax_rate2' => 0,
|
||||
'tax_rate3' => 0,
|
||||
'tax_name1' => '',
|
||||
'tax_name2' => '',
|
||||
'tax_name3' => '',
|
||||
'tax_data' => new Response([]),
|
||||
]);
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||
|
||||
$this->assertEquals(21, $invoice->line_items[0]->tax_rate1);
|
||||
$this->assertEquals(121, $invoice->amount);
|
||||
}
|
||||
|
||||
public function testInvoiceTaxCalcDetoBe()
|
||||
{
|
||||
$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,
|
||||
'tax_data' => $tax_data,
|
||||
'calculate_taxes' => true,
|
||||
]);
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 56,
|
||||
'shipping_country_id' => 56,
|
||||
'has_valid_vat_number' => true,
|
||||
]);
|
||||
|
||||
$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_rate1' => 0,
|
||||
'tax_rate2' => 0,
|
||||
'tax_rate3' => 0,
|
||||
'tax_name1' => '',
|
||||
'tax_name2' => '',
|
||||
'tax_name3' => '',
|
||||
'tax_data' => new Response([]),
|
||||
]);
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||
|
||||
$this->assertEquals(0, $invoice->line_items[0]->tax_rate1);
|
||||
$this->assertEquals(100, $invoice->amount);
|
||||
}
|
||||
|
||||
|
||||
public function testInvoiceTaxCalcDetoDe()
|
||||
{
|
||||
$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,
|
||||
'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' => true,
|
||||
]);
|
||||
|
||||
$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_rate1' => 0,
|
||||
'tax_rate2' => 0,
|
||||
'tax_rate3' => 0,
|
||||
'tax_name1' => '',
|
||||
'tax_name2' => '',
|
||||
'tax_name3' => '',
|
||||
'tax_data' => new Response([]),
|
||||
]);
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
|
||||
$this->assertEquals(19, $invoice->line_items[0]->tax_rate1);
|
||||
$this->assertEquals(119, $invoice->amount);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function testCorrectRuleInit()
|
||||
{
|
||||
|
||||
$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,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
$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,
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setClient($client);
|
||||
$process->init();
|
||||
|
||||
$this->assertEquals('DE', $process->vendor_country_code);
|
||||
|
||||
$this->assertEquals('DE', $process->client_country_code);
|
||||
|
||||
$this->assertFalse($client->has_valid_vat_number);
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
|
||||
$this->assertEquals(19, $process->vat_rate);
|
||||
|
||||
$this->assertEquals(7, $process->reduced_vat_rate);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testEuCorrectRuleInit()
|
||||
{
|
||||
|
||||
$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,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 56,
|
||||
'shipping_country_id' => 56,
|
||||
'has_valid_vat_number' => false,
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setClient($client);
|
||||
$process->init();
|
||||
|
||||
|
||||
$this->assertEquals('DE', $process->vendor_country_code);
|
||||
|
||||
$this->assertEquals('BE', $process->client_country_code);
|
||||
|
||||
$this->assertFalse($client->has_valid_vat_number);
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
|
||||
$this->assertEquals(21, $process->vat_rate);
|
||||
|
||||
$this->assertEquals(6, $process->reduced_vat_rate);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testForeignCorrectRuleInit()
|
||||
{
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->country_id = '276'; // germany
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings
|
||||
]);
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 840,
|
||||
'shipping_country_id' => 840,
|
||||
'has_valid_vat_number' => false,
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setClient($client);
|
||||
$process->init();
|
||||
|
||||
$this->assertEquals('DE', $process->vendor_country_code);
|
||||
|
||||
$this->assertEquals('US', $process->client_country_code);
|
||||
|
||||
$this->assertFalse($client->has_valid_vat_number);
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
|
||||
$this->assertEquals(0, $process->vat_rate);
|
||||
|
||||
$this->assertEquals(0, $process->reduced_vat_rate);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testSubThresholdCorrectRate()
|
||||
{
|
||||
|
||||
$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 = false;
|
||||
$tax_data->regions->EU->tax_all = true;
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 56,
|
||||
'shipping_country_id' => 56,
|
||||
'has_valid_vat_number' => false,
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setClient($client);
|
||||
$process->init();
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
|
||||
$this->assertFalse($client->has_valid_vat_number);
|
||||
|
||||
$this->assertEquals(19, $process->vat_rate);
|
||||
|
||||
$this->assertEquals(7, $process->reduced_vat_rate);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//tests with valid vat.
|
||||
public function testDeWithValidVat()
|
||||
{
|
||||
$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 = false;
|
||||
$tax_data->regions->EU->tax_all = true;
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 276,
|
||||
'shipping_country_id' => 276,
|
||||
'has_valid_vat_number' => true,
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setClient($client);
|
||||
$process->init();
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
|
||||
$this->assertTrue($client->has_valid_vat_number);
|
||||
|
||||
$this->assertEquals(19, $process->vat_rate);
|
||||
|
||||
$this->assertEquals(7, $process->reduced_vat_rate);
|
||||
|
||||
}
|
||||
|
||||
//tests with valid vat.
|
||||
public function testDeToEUWithValidVat()
|
||||
{
|
||||
$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 = false;
|
||||
$tax_data->regions->EU->tax_all = true;
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 56,
|
||||
'shipping_country_id' => 56,
|
||||
'has_valid_vat_number' => true,
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setClient($client);
|
||||
$process->init();
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
|
||||
$this->assertTrue($client->has_valid_vat_number);
|
||||
|
||||
$this->assertEquals(0, $process->vat_rate);
|
||||
|
||||
$this->assertEquals(0, $process->reduced_vat_rate);
|
||||
|
||||
}
|
||||
|
||||
public function testTaxExemptionDeSellerBeBuyer()
|
||||
{
|
||||
$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 = false;
|
||||
$tax_data->regions->EU->tax_all = true;
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 56,
|
||||
'shipping_country_id' => 56,
|
||||
'has_valid_vat_number' => true,
|
||||
'is_tax_exempt' => true,
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setClient($client);
|
||||
$process->init();
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
|
||||
$this->assertTrue($client->is_tax_exempt);
|
||||
|
||||
$this->assertEquals(0, $process->vat_rate);
|
||||
|
||||
$this->assertEquals(0, $process->reduced_vat_rate);
|
||||
|
||||
}
|
||||
|
||||
public function testTaxExemptionDeSellerDeBuyer()
|
||||
{
|
||||
$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 = false;
|
||||
$tax_data->regions->EU->tax_all = true;
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 276,
|
||||
'shipping_country_id' => 276,
|
||||
'has_valid_vat_number' => true,
|
||||
'is_tax_exempt' => true,
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setClient($client);
|
||||
$process->init();
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
|
||||
$this->assertTrue($client->is_tax_exempt);
|
||||
|
||||
$this->assertEquals(0, $process->vat_rate);
|
||||
|
||||
$this->assertEquals(0, $process->reduced_vat_rate);
|
||||
|
||||
}
|
||||
|
||||
public function testTaxExemption3()
|
||||
{
|
||||
$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 = false;
|
||||
$tax_data->regions->EU->tax_all = true;
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings,
|
||||
'tax_data' => $tax_data,
|
||||
]);
|
||||
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 840,
|
||||
'shipping_country_id' => 840,
|
||||
'has_valid_vat_number' => true,
|
||||
'is_tax_exempt' => true,
|
||||
]);
|
||||
|
||||
$process = new Rule();
|
||||
$process->setClient($client);
|
||||
$process->init();
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process);
|
||||
|
||||
$this->assertTrue($client->is_tax_exempt);
|
||||
|
||||
$this->assertEquals(0, $process->vat_rate);
|
||||
|
||||
$this->assertEquals(0, $process->reduced_vat_rate);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace Tests\Unit\Tax;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use Tests\MockAccountData;
|
||||
use App\DataMapper\Tax\de\Rule;
|
||||
use App\Services\Tax\ProcessRule;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
/**
|
||||
* @test App\Services\Tax\ProcessRule
|
||||
*/
|
||||
class ProcessRuleTest extends TestCase
|
||||
{
|
||||
use MockAccountData;
|
||||
use DatabaseTransactions;
|
||||
|
||||
protected function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
|
||||
$this->makeTestData();
|
||||
}
|
||||
|
||||
public function testCorrectRuleInit()
|
||||
{
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->country_id = '276'; // germany
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings
|
||||
]);
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 276,
|
||||
'shipping_country_id' => 276,
|
||||
]);
|
||||
|
||||
$process = new ProcessRule($company, $client);
|
||||
$process->run();
|
||||
|
||||
$this->assertEquals('de', $process->getVendorCountryCode());
|
||||
|
||||
$this->assertEquals('de', $process->getClientCountryCode());
|
||||
|
||||
$this->assertFalse($process->hasValidVatNumber());
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process->rule);
|
||||
|
||||
$this->assertEquals(19, $process->getVatRate());
|
||||
|
||||
$this->assertEquals(7, $process->getVatReducedRate());
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testEuCorrectRuleInit()
|
||||
{
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->country_id = '276'; // germany
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings
|
||||
]);
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 56,
|
||||
'shipping_country_id' => 56,
|
||||
]);
|
||||
|
||||
$process = new ProcessRule($company, $client);
|
||||
$process->run();
|
||||
|
||||
$this->assertEquals('de', $process->getVendorCountryCode());
|
||||
|
||||
$this->assertEquals('be', $process->getClientCountryCode());
|
||||
|
||||
$this->assertFalse($process->hasValidVatNumber());
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process->rule);
|
||||
|
||||
$this->assertEquals(21, $process->getVatRate());
|
||||
|
||||
$this->assertEquals(7, $process->getVatReducedRate());
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testForeignCorrectRuleInit()
|
||||
{
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->country_id = '276'; // germany
|
||||
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $this->account->id,
|
||||
'settings' => $settings
|
||||
]);
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $company->id,
|
||||
'country_id' => 840,
|
||||
'shipping_country_id' => 840,
|
||||
]);
|
||||
|
||||
$process = new ProcessRule($company, $client);
|
||||
$process->run();
|
||||
|
||||
$this->assertEquals('de', $process->getVendorCountryCode());
|
||||
|
||||
$this->assertEquals('us', $process->getClientCountryCode());
|
||||
|
||||
$this->assertFalse($process->hasValidVatNumber());
|
||||
|
||||
$this->assertInstanceOf(Rule::class, $process->rule);
|
||||
|
||||
$this->assertEquals(0, $process->getVatRate());
|
||||
|
||||
$this->assertEquals(0, $process->getVatReducedRate());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -12,7 +12,15 @@
|
||||
namespace Tests\Unit\Tax;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Product;
|
||||
use Tests\MockAccountData;
|
||||
use App\DataMapper\InvoiceItem;
|
||||
use App\DataMapper\Tax\TaxData;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\DataMapper\Tax\TaxModel;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
|
||||
@ -24,45 +32,43 @@ class SumTaxTest extends TestCase
|
||||
use MockAccountData;
|
||||
use DatabaseTransactions;
|
||||
|
||||
public array $response =
|
||||
["results" => [
|
||||
[
|
||||
"geoPostalCode" => "92582",
|
||||
"geoCity" => "SAN JACINTO",
|
||||
"geoCounty" => "RIVERSIDE",
|
||||
"geoState" => "CA",
|
||||
"taxSales" => 0.0875,
|
||||
"taxUse" => 0.0875, // tax amount where destination does not charge sales tax, but origin does
|
||||
"txbService" => "N", // whether services are taxed in this locale
|
||||
"txbFreight" => "N", // whether freight is taxes in this locale
|
||||
"stateSalesTax" => 0.06,
|
||||
"stateUseTax" => 0.06,
|
||||
"citySalesTax" => 0.01,
|
||||
"cityUseTax" => 0.01,
|
||||
"cityTaxCode" => "874",
|
||||
"countySalesTax" => 0.0025,
|
||||
"countyUseTax" => 0.0025,
|
||||
"countyTaxCode" => "",
|
||||
"districtSalesTax" => 0.015,
|
||||
"districtUseTax" => 0.015,
|
||||
"district1Code" => "26",
|
||||
"district1SalesTax" => 0,
|
||||
"district1UseTax" => 0,
|
||||
"district2Code" => "26",
|
||||
"district2SalesTax" => 0.005,
|
||||
"district2UseTax" => 0.005,
|
||||
"district3Code" => "",
|
||||
"district3SalesTax" => 0,
|
||||
"district3UseTax" => 0,
|
||||
"district4Code" => "33",
|
||||
"district4SalesTax" => 0.01,
|
||||
"district4UseTax" => 0.01,
|
||||
"district5Code" => "",
|
||||
"district5SalesTax" => 0,
|
||||
"district5UseTax" => 0, //district1-5 portion of the district tax
|
||||
"originDestination" => "D", //location where this is taxed origin/destination/null
|
||||
],
|
||||
]
|
||||
public Response $response;
|
||||
|
||||
public array $resp = [
|
||||
"geoPostalCode" => "92582",
|
||||
"geoCity" => "SAN JACINTO",
|
||||
"geoCounty" => "RIVERSIDE",
|
||||
"geoState" => "CA",
|
||||
"taxSales" => 0.0875,
|
||||
"taxUse" => 0.0875, // tax amount where destination does not charge sales tax, but origin does
|
||||
"txbService" => "N", // whether services are taxed in this locale
|
||||
"txbFreight" => "N", // whether freight is taxes in this locale
|
||||
"stateSalesTax" => 0.06,
|
||||
"stateUseTax" => 0.06,
|
||||
"citySalesTax" => 0.01,
|
||||
"cityUseTax" => 0.01,
|
||||
"cityTaxCode" => "874",
|
||||
"countySalesTax" => 0.0025,
|
||||
"countyUseTax" => 0.0025,
|
||||
"countyTaxCode" => "",
|
||||
"districtSalesTax" => 0.015,
|
||||
"districtUseTax" => 0.015,
|
||||
"district1Code" => "26",
|
||||
"district1SalesTax" => 0,
|
||||
"district1UseTax" => 0,
|
||||
"district2Code" => "26",
|
||||
"district2SalesTax" => 0.005,
|
||||
"district2UseTax" => 0.005,
|
||||
"district3Code" => "",
|
||||
"district3SalesTax" => 0,
|
||||
"district3UseTax" => 0,
|
||||
"district4Code" => "33",
|
||||
"district4SalesTax" => 0.01,
|
||||
"district4UseTax" => 0.01,
|
||||
"district5Code" => "",
|
||||
"district5SalesTax" => 0,
|
||||
"district5UseTax" => 0, //district1-5 portion of the district tax
|
||||
"originDestination" => "D", //location where this is taxed origin/destination/null
|
||||
];
|
||||
|
||||
|
||||
@ -76,37 +82,178 @@ class SumTaxTest extends TestCase
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
|
||||
// $this->makeTestData();
|
||||
$this->makeTestData();
|
||||
|
||||
$this->response = new Response($this->resp);
|
||||
|
||||
}
|
||||
|
||||
/** Proves that we do not charge taxes automatically */
|
||||
public function testCalcInvoiceNoTax()
|
||||
{
|
||||
|
||||
|
||||
$tax_data = new TaxModel();
|
||||
$tax_data->seller_region = 'US';
|
||||
$tax_data->seller_subregion = 'CA';
|
||||
$tax_data->regions->US->has_sales_above_threshold = true;
|
||||
$tax_data->regions->US->tax_all = true;
|
||||
|
||||
$this->company->calculate_taxes = false;
|
||||
$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,
|
||||
]);
|
||||
|
||||
$invoice = InvoiceFactory::create($this->company->id, $this->user->id);
|
||||
$invoice->client_id = $client->id;
|
||||
$invoice->uses_inclusive_taxes = false;
|
||||
|
||||
$line_items = [];
|
||||
|
||||
$invoice->tax_data = new TaxData($this->response);
|
||||
|
||||
$line_item = new InvoiceItem();
|
||||
$line_item->quantity = 1;
|
||||
$line_item->cost = 10;
|
||||
$line_item->product_key = 'Test';
|
||||
$line_item->notes = 'Test';
|
||||
$line_item->tax_id = Product::PRODUCT_TYPE_PHYSICAL;
|
||||
$line_items[] = $line_item;
|
||||
|
||||
$invoice->line_items = $line_items;
|
||||
$invoice->save();
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
/** Proves that we do calc taxes automatically */
|
||||
public function testCalcInvoiceTax()
|
||||
{
|
||||
|
||||
|
||||
|
||||
$tax_data = new TaxModel();
|
||||
$tax_data->seller_region = 'US';
|
||||
$tax_data->seller_subregion = 'CA';
|
||||
$tax_data->regions->US->has_sales_above_threshold = true;
|
||||
$tax_data->regions->US->tax_all = true;
|
||||
|
||||
$this->company->calculate_taxes = true;
|
||||
$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,
|
||||
]);
|
||||
|
||||
$invoice = InvoiceFactory::create($this->company->id, $this->user->id);
|
||||
$invoice->client_id = $client->id;
|
||||
$invoice->uses_inclusive_taxes = false;
|
||||
|
||||
$line_items = [];
|
||||
|
||||
$invoice->tax_data = new TaxData($this->response);
|
||||
|
||||
$line_item = new InvoiceItem;
|
||||
$line_item->quantity = 1;
|
||||
$line_item->cost = 10;
|
||||
$line_item->product_key = 'Test';
|
||||
$line_item->notes = 'Test';
|
||||
$line_item->tax_id = Product::PRODUCT_TYPE_PHYSICAL;
|
||||
$line_items[] = $line_item;
|
||||
|
||||
$invoice->line_items = $line_items;
|
||||
$invoice->save();
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
|
||||
$line_items = $invoice->line_items;
|
||||
|
||||
|
||||
$this->assertEquals(10.88, $invoice->amount);
|
||||
$this->assertEquals("CA Sales Tax", $line_items[0]->tax_name1);
|
||||
$this->assertEquals(8.75, $line_items[0]->tax_rate1);
|
||||
}
|
||||
|
||||
public function testTaxOnCompany()
|
||||
{
|
||||
|
||||
$tax_class = new TaxData($this->response);
|
||||
|
||||
$this->company->tax_data = $tax_class;
|
||||
$this->company->save();
|
||||
|
||||
$this->assertEquals("92582", $this->company->tax_data->origin->geoPostalCode);
|
||||
$this->assertEquals(0.0875, $this->company->tax_data->origin->taxSales);
|
||||
|
||||
}
|
||||
|
||||
public function testTaxOnClient()
|
||||
{
|
||||
$c = Client::factory()->create([
|
||||
'user_id' => $this->user->id,
|
||||
'company_id' => $this->company->id,
|
||||
]);
|
||||
|
||||
$tax_class = new TaxData($this->response, $this->response);
|
||||
|
||||
$c->tax_data = $tax_class;
|
||||
$c->save();
|
||||
|
||||
$this->assertEquals("92582", $c->tax_data->origin->geoPostalCode);
|
||||
$this->assertEquals(0.0875, $c->tax_data->origin->taxSales);
|
||||
|
||||
}
|
||||
|
||||
public function testTaxOnInvoice()
|
||||
{
|
||||
|
||||
$i = Invoice::factory()->create([
|
||||
'company_id' => $this->company->id,
|
||||
'client_id' => $this->client->id,
|
||||
'user_id' => $this->user->id,
|
||||
]);
|
||||
|
||||
$tax_class = new TaxData($this->response);
|
||||
|
||||
$i->tax_data = $tax_class;
|
||||
$i->save();
|
||||
|
||||
|
||||
$this->assertEquals("92582", $i->tax_data->origin->geoPostalCode);
|
||||
$this->assertEquals(0.0875, $i->tax_data->origin->taxSales);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testSumOfInvoice()
|
||||
{
|
||||
|
||||
$this->assertEquals("CA", $this->response['results'][0]['geoState']);
|
||||
$this->assertEquals("CA", $this->response->geoState);
|
||||
|
||||
}
|
||||
|
||||
public function testSumOfTaxes()
|
||||
{
|
||||
$sum =
|
||||
$this->response['results'][0]['stateSalesTax'] +
|
||||
// $this->response['results'][0]['stateUseTax'] +
|
||||
$this->response['results'][0]['citySalesTax'] +
|
||||
// $this->response['results'][0]['cityUseTax'] +
|
||||
$this->response['results'][0]['countySalesTax'] +
|
||||
// $this->response['results'][0]['countyUseTax'] +
|
||||
$this->response['results'][0]['districtSalesTax'];
|
||||
// // $this->response['results'][0]['districtUseTax'] +
|
||||
// $this->response['results'][0]['district1SalesTax'] +
|
||||
// // $this->response['results'][0]['district1UseTax'] +
|
||||
// $this->response['results'][0]['district2SalesTax'] +
|
||||
// // $this->response['results'][0]['district2UseTax'] +
|
||||
// $this->response['results'][0]['district3SalesTax'] +
|
||||
// // $this->response['results'][0]['district3UseTax'] +
|
||||
// $this->response['results'][0]['district4SalesTax'] +
|
||||
// // $this->response['results'][0]['district4UseTax'] +
|
||||
// $this->response['results'][0]['district5SalesTax'];
|
||||
// $this->response['results'][0]['district5UseTax'];
|
||||
$this->response->stateSalesTax +
|
||||
$this->response->citySalesTax +
|
||||
$this->response->countySalesTax +
|
||||
$this->response->districtSalesTax;
|
||||
|
||||
$this->assertEquals(0.0875, $sum);
|
||||
}
|
||||
|
287
tests/Unit/Tax/UsTaxTest.php
Normal file
287
tests/Unit/Tax/UsTaxTest.php
Normal file
@ -0,0 +1,287 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace Tests\Unit\Tax;
|
||||
|
||||
use Tests\TestCase;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
class UsTaxTest extends TestCase
|
||||
{
|
||||
use MockAccountData;
|
||||
use DatabaseTransactions;
|
||||
|
||||
private array $mock_response = [
|
||||
"geoPostalCode" => "92582",
|
||||
"geoCity" => "SAN JACINTO",
|
||||
"geoCounty" => "RIVERSIDE",
|
||||
"geoState" => "CA",
|
||||
"taxSales" => 0.0875,
|
||||
"taxUse" => 0.0875,
|
||||
"txbService" => "N",
|
||||
"txbFreight" => "N",
|
||||
"stateSalesTax" => 0.06,
|
||||
"stateUseTax" => 0.06,
|
||||
"citySalesTax" => 0.01,
|
||||
"cityUseTax" => 0.01,
|
||||
"cityTaxCode" => "874",
|
||||
"countySalesTax" => 0.0025,
|
||||
"countyUseTax" => 0.0025,
|
||||
"countyTaxCode" => "",
|
||||
"districtSalesTax" => 0.015,
|
||||
"districtUseTax" => 0.015,
|
||||
"district1Code" => "26",
|
||||
"district1SalesTax" => 0,
|
||||
"district1UseTax" => 0,
|
||||
"district2Code" => "26",
|
||||
"district2SalesTax" => 0.005,
|
||||
"district2UseTax" => 0.005,
|
||||
"district3Code" => "",
|
||||
"district3SalesTax" => 0,
|
||||
"district3UseTax" => 0,
|
||||
"district4Code" => "33",
|
||||
"district4SalesTax" => 0.01,
|
||||
"district4UseTax" => 0.01,
|
||||
"district5Code" => "",
|
||||
"district5SalesTax" => 0,
|
||||
"district5UseTax" => 0,
|
||||
"originDestination" => "D",
|
||||
];
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
|
||||
$this->makeTestData();
|
||||
}
|
||||
|
||||
private function invoiceStub(?string $postal_code = '')
|
||||
{
|
||||
|
||||
$settings = CompanySettings::defaults();
|
||||
$settings->country_id = '840'; // germany
|
||||
|
||||
$tax_data = new TaxModel();
|
||||
$tax_data->seller_region = 'US';
|
||||
$tax_data->seller_subregion = 'CA';
|
||||
$tax_data->regions->US->has_sales_above_threshold = true;
|
||||
$tax_data->regions->US->tax_all = true;
|
||||
|
||||
$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' => 840,
|
||||
'shipping_country_id' => 840,
|
||||
'has_valid_vat_number' => false,
|
||||
'postal_code' => $postal_code,
|
||||
]);
|
||||
|
||||
$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_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();
|
||||
|
||||
return $invoice;
|
||||
}
|
||||
|
||||
// public function testCompanyTaxAllOffTaxExemptProduct()
|
||||
// {
|
||||
|
||||
// $invoice = $this->invoiceStub('92582');
|
||||
// $client = $invoice->client;
|
||||
// $client->is_tax_exempt = false;
|
||||
// $client->save();
|
||||
|
||||
// $company = $invoice->company;
|
||||
// $tax_data = $company->tax_data;
|
||||
|
||||
// $tax_data->regions->US->has_sales_above_threshold = true;
|
||||
// $tax_data->regions->US->tax_all = false;
|
||||
|
||||
// $company->tax_data = $tax_data;
|
||||
// $company->save();
|
||||
|
||||
// $invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||
|
||||
// $this->assertEquals(0, $invoice->line_items[0]->tax_rate1);
|
||||
// $this->assertEquals(100, $invoice->amount);
|
||||
|
||||
// }
|
||||
|
||||
public function testCompanyTaxAllOffButTaxUSRegion()
|
||||
{
|
||||
|
||||
$invoice = $this->invoiceStub('92582');
|
||||
$client = $invoice->client;
|
||||
$client->is_tax_exempt = false;
|
||||
$client->save();
|
||||
|
||||
$company = $invoice->company;
|
||||
$tax_data = $company->tax_data;
|
||||
|
||||
$tax_data->regions->US->has_sales_above_threshold = true;
|
||||
$tax_data->regions->US->tax_all = true;
|
||||
|
||||
$company->tax_data = $tax_data;
|
||||
$company->save();
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||
|
||||
$this->assertEquals(8.75, $invoice->line_items[0]->tax_rate1);
|
||||
$this->assertEquals(108.75, $invoice->amount);
|
||||
|
||||
}
|
||||
|
||||
public function testCompanyTaxAllOff()
|
||||
{
|
||||
|
||||
$invoice = $this->invoiceStub('92582');
|
||||
$client = $invoice->client;
|
||||
$client->is_tax_exempt = false;
|
||||
$client->save();
|
||||
|
||||
$company = $invoice->company;
|
||||
$tax_data = $company->tax_data;
|
||||
|
||||
$tax_data->regions->US->has_sales_above_threshold = true;
|
||||
$tax_data->regions->US->tax_all = false;
|
||||
|
||||
$company->tax_data = $tax_data;
|
||||
$company->save();
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||
|
||||
$this->assertEquals(0, $invoice->line_items[0]->tax_rate1);
|
||||
$this->assertEquals(100, $invoice->amount);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function testThresholdLevelsAreMet()
|
||||
{
|
||||
|
||||
$invoice = $this->invoiceStub('92582');
|
||||
$client = $invoice->client;
|
||||
$client->is_tax_exempt = true;
|
||||
$client->save();
|
||||
|
||||
|
||||
$company = $invoice->company;
|
||||
$tax_data = $company->tax_data;
|
||||
|
||||
$tax_data->regions->US->has_sales_above_threshold = false;
|
||||
$tax_data->regions->US->tax_all = true;
|
||||
|
||||
$company->tax_data = $tax_data;
|
||||
$company->save();
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||
|
||||
$this->assertEquals(0, $invoice->line_items[0]->tax_rate1);
|
||||
$this->assertEquals(100, $invoice->amount);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function testHasValidVatMakesNoDifferenceToTaxCalc()
|
||||
{
|
||||
|
||||
$invoice = $this->invoiceStub('92582');
|
||||
$client = $invoice->client;
|
||||
$client->has_valid_vat_number = true;
|
||||
$client->save();
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||
|
||||
$this->assertEquals(8.75, $invoice->line_items[0]->tax_rate1);
|
||||
$this->assertEquals(108.75, $invoice->amount);
|
||||
}
|
||||
|
||||
|
||||
public function testTaxExemption()
|
||||
{
|
||||
$invoice = $this->invoiceStub('92582');
|
||||
$client = $invoice->client;
|
||||
$client->is_tax_exempt = true;
|
||||
$client->save();
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice()->service()->markSent()->save();
|
||||
|
||||
$this->assertEquals(0, $invoice->line_items[0]->tax_rate1);
|
||||
$this->assertEquals(100, $invoice->amount);
|
||||
}
|
||||
|
||||
public function testBasicTaxCalculation()
|
||||
{
|
||||
|
||||
$invoice = $this->invoiceStub();
|
||||
|
||||
|
||||
$this->assertEquals(8.75, $invoice->line_items[0]->tax_rate1);
|
||||
$this->assertEquals(108.75, $invoice->amount);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user