2023-03-26 22:46:26 +02:00
< ? 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 ;
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 ;
2023-06-02 07:53:33 +02:00
private bool $updated_client = false ;
2023-05-17 06:07:48 +02:00
public function __construct ( public Company $company , public ? Client $client = null )
2023-03-26 22:46:26 +02:00
{
}
2023-05-25 02:38:43 +02:00
2023-06-02 07:53:33 +02:00
/**
* Flag if tax has been updated successfull .
*
* @ return bool
*/
public function updatedTaxStatus () : bool
{
return $this -> updated_client ;
}
2023-05-25 02:38:43 +02:00
/**
* updateCompanyTaxData
*
* @ return self
*/
2023-03-26 22:46:26 +02:00
public function updateCompanyTaxData () : self
{
2023-09-17 04:40:24 +02:00
try {
2023-10-26 04:57:44 +02:00
$this -> configureProvider ( $this -> provider , $this -> company -> country () -> iso_3166_2 ); //hard coded for now to one provider, but we'll be able to swap these out later
2023-03-26 22:46:26 +02:00
2023-09-17 04:40:24 +02:00
$company_details = [
'address2' => $this -> company -> settings -> address2 ,
'address1' => $this -> company -> settings -> address1 ,
'city' => $this -> company -> settings -> city ,
'state' => $this -> company -> settings -> state ,
'postal_code' => $this -> company -> settings -> postal_code ,
'country' => $this -> company -> country () -> name ,
];
2023-03-26 22:46:26 +02:00
2023-06-02 07:53:33 +02:00
$tax_provider = new $this -> provider ( $company_details );
2023-03-26 22:46:26 +02:00
2023-06-02 07:53:33 +02:00
$tax_provider -> setApiCredentials ( $this -> api_credentials );
$tax_data = $tax_provider -> run ();
if ( $tax_data ) {
$this -> company -> origin_tax_data = $tax_data ;
$this -> company -> saveQuietly ();
$this -> updated_client = true ;
}
2023-10-26 04:57:44 +02:00
} catch ( \Exception $e ) {
2023-06-02 07:53:33 +02:00
nlog ( " Could not updated company tax data: " . $e -> getMessage ());
}
2023-03-26 22:46:26 +02:00
return $this ;
}
2023-05-25 02:38:43 +02:00
/**
* updateClientTaxData
*
* @ return self
*/
2023-03-26 22:46:26 +02:00
public function updateClientTaxData () : self
{
2023-05-17 06:07:48 +02:00
$this -> configureProvider ( $this -> provider , $this -> client -> country -> iso_3166_2 ); //hard coded for now to one provider, but we'll be able to swap these out later
2023-03-26 22:46:26 +02:00
$billing_details = [
'address2' => $this -> client -> address2 ,
2023-06-02 07:53:33 +02:00
'address1' => $this -> client -> address1 ,
2023-03-26 22:46:26 +02:00
'city' => $this -> client -> city ,
'state' => $this -> client -> state ,
'postal_code' => $this -> client -> postal_code ,
2023-06-02 07:53:33 +02:00
'country' => $this -> client -> country -> name ,
2023-03-26 22:46:26 +02:00
];
$shipping_details = [
'address2' => $this -> client -> shipping_address2 ,
2023-06-02 07:53:33 +02:00
'address1' => $this -> client -> shipping_address1 ,
2023-03-26 22:46:26 +02:00
'city' => $this -> client -> shipping_city ,
'state' => $this -> client -> shipping_state ,
'postal_code' => $this -> client -> shipping_postal_code ,
2023-06-22 08:54:30 +02:00
'country' => $this -> client -> shipping_country () -> exists () ? $this -> client -> shipping_country -> name : $this -> client -> country -> name ,
2023-03-26 22:46:26 +02:00
];
2023-05-25 02:38:43 +02:00
$taxable_address = $this -> taxShippingAddress () ? $shipping_details : $billing_details ;
$tax_provider = new $this -> provider ( $taxable_address );
2023-03-26 22:46:26 +02:00
$tax_provider -> setApiCredentials ( $this -> api_credentials );
$tax_data = $tax_provider -> run ();
2023-06-02 07:53:33 +02:00
2023-09-17 04:40:24 +02:00
// nlog($tax_data);
2023-03-26 22:46:26 +02:00
2023-06-02 07:53:33 +02:00
if ( $tax_data ) {
$this -> client -> tax_data = $tax_data ;
$this -> client -> saveQuietly ();
$this -> updated_client = true ;
}
2023-03-26 22:46:26 +02:00
return $this ;
}
2023-05-25 02:38:43 +02:00
/**
* taxShippingAddress
*
* @ return bool
*/
private function taxShippingAddress () : bool
{
2023-10-26 04:57:44 +02:00
if ( $this -> client -> shipping_country_id == " 840 " && strlen ( $this -> client -> shipping_postal_code ) > 3 ) {
2023-05-25 02:38:43 +02:00
return true ;
2023-10-26 04:57:44 +02:00
}
2023-03-26 22:46:26 +02:00
2023-05-25 02:38:43 +02:00
return false ;
}
/**
* configureProvider
*
* @ param string $provider
* @ param string $country_code
* @ return self
*/
2023-05-17 06:07:48 +02:00
private function configureProvider ( ? string $provider , string $country_code ) : self
2023-03-26 22:46:26 +02:00
{
2023-10-26 04:57:44 +02:00
match ( $country_code ) {
2023-03-26 22:46:26 +02:00
'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 ;
}
2023-05-25 02:38:43 +02:00
/**
* configureEuTax
*
* @ return self
*/
2023-03-26 22:46:26 +02:00
private function configureEuTax () : self
{
2023-10-19 02:23:13 +02:00
throw new \Exception ( " No tax region defined for this country " );
2023-03-26 22:46:26 +02:00
$this -> provider = EuTax :: class ;
return $this ;
}
2023-05-25 02:38:43 +02:00
/**
* noTaxRegionDefined
*
* @ return void
*/
2023-05-17 06:07:48 +02:00
private function noTaxRegionDefined ()
2023-03-26 22:46:26 +02:00
{
2023-03-27 05:47:01 +02:00
throw new \Exception ( " No tax region defined for this country " );
2023-05-17 06:07:48 +02:00
// return $this;
2023-03-26 22:46:26 +02:00
}
2023-05-25 02:38:43 +02:00
/**
* configureZipTax
*
* @ return self
*/
2023-03-26 22:46:26 +02:00
private function configureZipTax () : self
{
2023-10-26 04:57:44 +02:00
if ( ! config ( 'services.tax.zip_tax.key' )) {
2023-06-02 07:53:33 +02:00
throw new \Exception ( " ZipTax API key not set in .env file " );
2023-10-26 04:57:44 +02:00
}
2023-03-26 22:46:26 +02:00
$this -> api_credentials = config ( 'services.tax.zip_tax.key' );
2023-06-02 07:53:33 +02:00
$this -> provider = ZipTax :: class ;
2023-03-26 22:46:26 +02:00
return $this ;
}
2023-10-26 04:57:44 +02:00
}