mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Merge branch 'v5-develop' into v5-stable
This commit is contained in:
commit
1c8a248828
3
.env.ci
3
.env.ci
@ -21,3 +21,6 @@ COMPOSER_AUTH='{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}'
|
||||
TRAVIS=true
|
||||
API_SECRET=superdoopersecrethere
|
||||
PHANTOMJS_PDF_GENERATION=false
|
||||
CACHE_DRIVER=redis
|
||||
QUEUE_CONNECTION=redis
|
||||
SESSION_DRIVER=redis
|
@ -4,6 +4,7 @@ APP_KEY=base64:RR++yx2rJ9kdxbdh3+AmbHLDQu+Q76i++co9Y8ybbno=
|
||||
APP_DEBUG=false
|
||||
|
||||
APP_URL=http://localhost
|
||||
REACT_URL=http://localhost:3001
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
MULTI_DB_ENABLED=false
|
||||
@ -33,8 +34,8 @@ MAIL_PORT=2525
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS='user@example.com'
|
||||
MAIL_FROM_NAME='Self Hosted User'
|
||||
MAIL_FROM_ADDRESS="user@example.com"
|
||||
MAIL_FROM_NAME="Self Hosted User"
|
||||
|
||||
POSTMARK_API_TOKEN=
|
||||
REQUIRE_HTTPS=false
|
||||
@ -67,4 +68,4 @@ MICROSOFT_REDIRECT_URI=
|
||||
|
||||
APPLE_CLIENT_ID=
|
||||
APPLE_CLIENT_SECRET=
|
||||
APPLE_REDIRECT_URI=
|
||||
APPLE_REDIRECT_URI=
|
10
.github/workflows/phpunit.yml
vendored
10
.github/workflows/phpunit.yml
vendored
@ -22,6 +22,7 @@ jobs:
|
||||
dependency-version: [prefer-stable]
|
||||
|
||||
env:
|
||||
DB_CONNECTION: mysql
|
||||
DB_DATABASE1: ninja
|
||||
DB_USERNAME1: root
|
||||
DB_PASSWORD1: ninja
|
||||
@ -43,7 +44,7 @@ jobs:
|
||||
|
||||
services:
|
||||
mariadb:
|
||||
image: mariadb:latest
|
||||
image: mariadb:10.6
|
||||
ports:
|
||||
- 32768:3306
|
||||
env:
|
||||
@ -112,11 +113,10 @@ jobs:
|
||||
REDIS_PORT: ${{ job.services.redis.ports['6379'] }}
|
||||
run: |
|
||||
php artisan key:generate
|
||||
php artisan optimize
|
||||
php artisan cache:clear
|
||||
php artisan config:cache
|
||||
php artisan config:clear
|
||||
php artisan ninja:post-update
|
||||
|
||||
php artisan optimize
|
||||
|
||||
- name: Migrate Database
|
||||
run: |
|
||||
php artisan migrate:fresh --seed --force && php artisan db:seed --force
|
||||
|
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
||||
- name: Copy .env file
|
||||
run: |
|
||||
cp .env.example .env
|
||||
|
||||
|
||||
- name: Install composer dependencies
|
||||
run: |
|
||||
composer config -g github-oauth.github.com ${{ secrets.GITHUB_TOKEN }}
|
||||
@ -46,7 +46,9 @@ jobs:
|
||||
git checkout main
|
||||
npm i
|
||||
npm run build
|
||||
cp -r dist/react/* ../public/react
|
||||
cp -r dist/react/* ../public/react
|
||||
mkdir -p ../public/tinymce_6.4.2/tinymce/js/
|
||||
cp -r node_modules/tinymce ../public/tinymce_6.4.2/tinymce/js/
|
||||
cd ..
|
||||
rm -rf ui
|
||||
php artisan ninja:react
|
||||
@ -65,8 +67,9 @@ jobs:
|
||||
|
||||
- name: Build project
|
||||
run: |
|
||||
zip -r ./invoiceninja.zip .* -x "../*"
|
||||
|
||||
zip -r /home/runner/work/invoiceninja/invoiceninja.zip .* -x "../*"
|
||||
shopt -s dotglob
|
||||
tar --exclude='public/storage' --exclude='.htaccess' --exclude='invoiceninja.zip' -zcvf /home/runner/work/invoiceninja/invoiceninja.tar *
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
@ -74,4 +77,5 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
files: |
|
||||
invoiceninja.zip
|
||||
/home/runner/work/invoiceninja/invoiceninja.tar
|
||||
/home/runner/work/invoiceninja/invoiceninja.zip
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -37,4 +37,6 @@ public/test.pdf
|
||||
public/storage/test.pdf
|
||||
/Modules
|
||||
_ide_helper_models.php
|
||||
_ide_helper.php
|
||||
_ide_helper.php
|
||||
/composer.phar
|
||||
.tx/
|
@ -1 +1 @@
|
||||
5.5.102
|
||||
5.6.20
|
27
app/Casts/EncryptedCast.php
Normal file
27
app/Casts/EncryptedCast.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?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 App\Casts;
|
||||
|
||||
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
|
||||
|
||||
class EncryptedCast implements CastsAttributes
|
||||
{
|
||||
public function get($model, string $key, $value, array $attributes)
|
||||
{
|
||||
return is_string($value) && strlen($value) > 1 ? decrypt($value) : null;
|
||||
}
|
||||
|
||||
public function set($model, string $key, $value, array $attributes)
|
||||
{
|
||||
return [$key => ! is_null($value) ? encrypt($value) : null];
|
||||
}
|
||||
}
|
@ -11,11 +11,12 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Utils\Ninja;
|
||||
use App\Models\Backup;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\Document;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\GroupSetting;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@ -55,6 +56,9 @@ class BackupUpdate extends Command
|
||||
{
|
||||
//always return state to first DB
|
||||
|
||||
if(Ninja::isSelfHost())
|
||||
return;
|
||||
|
||||
$current_db = config('database.default');
|
||||
|
||||
if (! config('ninja.db.multi_db_enabled')) {
|
||||
|
@ -12,36 +12,37 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App;
|
||||
use Exception;
|
||||
use App\Models\User;
|
||||
use App\Utils\Ninja;
|
||||
use App\Models\Quote;
|
||||
use App\Models\Client;
|
||||
use App\Models\Credit;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\Account;
|
||||
use App\Models\Company;
|
||||
use App\Models\Contact;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\CompanyUser;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Models\CompanyToken;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\CompanyLedger;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\VendorContact;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\QuoteInvitation;
|
||||
use Illuminate\Console\Command;
|
||||
use App\Models\CreditInvitation;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\DataMapper\ClientSettings;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use App\Factory\ClientContactFactory;
|
||||
use App\Factory\VendorContactFactory;
|
||||
use App\Jobs\Company\CreateCompanyToken;
|
||||
use App\Models\Account;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyLedger;
|
||||
use App\Models\CompanyToken;
|
||||
use App\Models\CompanyUser;
|
||||
use App\Models\Contact;
|
||||
use App\Models\Credit;
|
||||
use App\Models\CreditInvitation;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\Quote;
|
||||
use App\Models\QuoteInvitation;
|
||||
use App\Models\RecurringInvoiceInvitation;
|
||||
use App\Models\User;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\VendorContact;
|
||||
use App\Utils\Ninja;
|
||||
use Exception;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
/*
|
||||
@ -81,7 +82,7 @@ class CheckData extends Command
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ninja:check-data {--database=} {--fix=} {--portal_url=} {--client_id=} {--vendor_id=} {--paid_to_date=} {--client_balance=} {--ledger_balance=} {--balance_status=}';
|
||||
protected $signature = 'ninja:check-data {--database=} {--fix=} {--portal_url=} {--client_id=} {--vendor_id=} {--paid_to_date=} {--client_balance=} {--ledger_balance=} {--balance_status=} {--bank_transaction=}';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -126,7 +127,8 @@ class CheckData extends Command
|
||||
$this->checkClientSettings();
|
||||
$this->checkCompanyTokens();
|
||||
$this->checkUserState();
|
||||
|
||||
$this->checkContactEmailAndSendEmailStatus();
|
||||
|
||||
if (Ninja::isHosted()) {
|
||||
$this->checkAccountStatuses();
|
||||
$this->checkNinjaPortalUrls();
|
||||
@ -136,6 +138,10 @@ class CheckData extends Command
|
||||
$this->checkOAuth();
|
||||
}
|
||||
|
||||
if($this->option('bank_transaction')) {
|
||||
$this->fixBankTransactions();
|
||||
}
|
||||
|
||||
$this->logMessage('Done: '.strtoupper($this->isValid ? Account::RESULT_SUCCESS : Account::RESULT_FAILURE));
|
||||
$this->logMessage('Total execution time in seconds: ' . (microtime(true) - $time_start));
|
||||
|
||||
@ -148,7 +154,7 @@ class CheckData extends Command
|
||||
->subject('Check-Data: '.strtoupper($this->isValid ? Account::RESULT_SUCCESS : Account::RESULT_FAILURE)." [{$database}]");
|
||||
});
|
||||
} elseif (! $this->isValid) {
|
||||
new Exception("Check data failed!!\n".$this->log);
|
||||
new \Exception("Check data failed!!".$this->log);
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,8 +416,8 @@ class CheckData extends Command
|
||||
$invitation->company_id = $invoice->company_id;
|
||||
$invitation->user_id = $invoice->user_id;
|
||||
$invitation->invoice_id = $invoice->id;
|
||||
$invitation->contact_id = ClientContact::whereClientId($invoice->client_id)->first()->id;
|
||||
$invitation->invitation_key = Str::random(config('ninja.key_length'));
|
||||
$invitation->client_contact_id = ClientContact::whereClientId($invoice->client_id)->first()->id;
|
||||
$invitation->key = Str::random(config('ninja.key_length'));
|
||||
$invitation->save();
|
||||
}
|
||||
}
|
||||
@ -429,11 +435,38 @@ class CheckData extends Command
|
||||
|
||||
private function checkEntityInvitations()
|
||||
{
|
||||
|
||||
RecurringInvoiceInvitation::where('deleted_at', "0000-00-00 00:00:00.000000")->withTrashed()->update(['deleted_at' => null]);
|
||||
InvoiceInvitation::where('deleted_at', "0000-00-00 00:00:00.000000")->withTrashed()->update(['deleted_at' => null]);
|
||||
QuoteInvitation::where('deleted_at', "0000-00-00 00:00:00.000000")->withTrashed()->update(['deleted_at' => null]);
|
||||
CreditInvitation::where('deleted_at', "0000-00-00 00:00:00.000000")->withTrashed()->update(['deleted_at' => null]);
|
||||
|
||||
InvoiceInvitation::where('sent_date', '0000-00-00 00:00:00')->cursor()->each(function ($ii){
|
||||
$ii->sent_date = null;
|
||||
$ii->saveQuietly();
|
||||
});
|
||||
InvoiceInvitation::where('viewed_date', '0000-00-00 00:00:00')->cursor()->each(function ($ii) {
|
||||
$ii->viewed_date = null;
|
||||
$ii->saveQuietly();
|
||||
});
|
||||
|
||||
QuoteInvitation::where('sent_date', '0000-00-00 00:00:00')->cursor()->each(function ($ii) {
|
||||
$ii->sent_date = null;
|
||||
$ii->saveQuietly();
|
||||
});
|
||||
QuoteInvitation::where('viewed_date', '0000-00-00 00:00:00')->cursor()->each(function ($ii) {
|
||||
$ii->viewed_date = null;
|
||||
$ii->saveQuietly();
|
||||
});
|
||||
|
||||
CreditInvitation::where('sent_date', '0000-00-00 00:00:00')->cursor()->each(function ($ii) {
|
||||
$ii->sent_date = null;
|
||||
$ii->saveQuietly();
|
||||
});
|
||||
CreditInvitation::where('viewed_date', '0000-00-00 00:00:00')->cursor()->each(function ($ii) {
|
||||
$ii->viewed_date = null;
|
||||
$ii->saveQuietly();
|
||||
});
|
||||
|
||||
collect([Invoice::class, Quote::class, Credit::class, PurchaseOrder::class])->each(function ($entity) {
|
||||
if ($entity::doesntHave('invitations')->count() > 0) {
|
||||
@ -442,7 +475,7 @@ class CheckData extends Command
|
||||
$contact_id = 'client_contact_id';
|
||||
$contact_class = ClientContact::class;
|
||||
|
||||
$entity_key = \Illuminate\Support\Str::of(class_basename($entity))->snake()->append('_id')->value;
|
||||
$entity_key = \Illuminate\Support\Str::of(class_basename($entity))->snake()->append('_id')->toString();
|
||||
$entity_obj = get_class($entity).'Invitation';
|
||||
|
||||
if ($entity instanceof PurchaseOrder) {
|
||||
@ -1090,4 +1123,42 @@ class CheckData extends Command
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public function fixBankTransactions()
|
||||
{
|
||||
$this->logMessage("checking bank transactions");
|
||||
|
||||
BankTransaction::with('payment')->withTrashed()->where('invoice_ids', ',,,,,,,,')->cursor()->each(function ($bt){
|
||||
|
||||
if($bt->payment->exists()) {
|
||||
|
||||
$bt->invoice_ids = collect($bt->payment->invoices)->pluck('hashed_id')->implode(',');
|
||||
$bt->save();
|
||||
|
||||
$this->logMessage("Fixing - {$bt->id}");
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public function checkContactEmailAndSendEmailStatus()
|
||||
{
|
||||
$q = ClientContact::whereNull('email')
|
||||
->where('send_email', true);
|
||||
|
||||
$this->logMessage($q->count() . " Contacts with Send Email = true but no email address");
|
||||
|
||||
if ($this->option('fix') == 'true') {
|
||||
|
||||
$q->cursor()->each(function ($c){
|
||||
$c->send_email = false;
|
||||
$c->saveQuietly();
|
||||
|
||||
$this->logMessage("Fixing - {$c->id}");
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,11 +42,6 @@ class CreateAccount extends Command
|
||||
*/
|
||||
protected $signature = 'ninja:create-account {--email=} {--password=}';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param InvoiceRepository $invoice_repo
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
@ -60,7 +60,7 @@ class DesignUpdate extends Command
|
||||
foreach (MultiDB::$dbs as $db) {
|
||||
MultiDB::setDB($db);
|
||||
|
||||
$this->handleOnDb($db);
|
||||
$this->handleOnDb();
|
||||
}
|
||||
|
||||
MultiDB::setDB($current_db);
|
||||
|
@ -105,7 +105,7 @@ class HostedMigrations extends Command
|
||||
|
||||
Import::dispatch($import_file, $user->companies()->first(), $user);
|
||||
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing $e) {
|
||||
\Mail::to($this->user)->send(new MigrationFailed($e, $e->getMessage()));
|
||||
\Mail::to($user)->send(new MigrationFailed($e, $company));
|
||||
|
||||
if (app()->environment() !== 'production') {
|
||||
info($e->getMessage());
|
||||
|
@ -44,7 +44,6 @@ class HostedUsers extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
@ -64,8 +64,6 @@ class ImportMigrations extends Command
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->faker = Factory::create();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
@ -76,6 +74,8 @@ class ImportMigrations extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->faker = Factory::create();
|
||||
|
||||
$this->buildCache();
|
||||
|
||||
$path = $this->option('path') ?? public_path('storage/migrations/import');
|
||||
@ -105,9 +105,9 @@ class ImportMigrations extends Command
|
||||
$import_file = public_path("storage/migrations/$filename/migration.json");
|
||||
|
||||
Import::dispatch($import_file, $this->getUser()->companies()->first(), $this->getUser());
|
||||
// StartMigration::dispatch($file->getRealPath(), $this->getUser(), $this->getUser()->companies()->first());
|
||||
|
||||
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing $e) {
|
||||
\Mail::to($this->user)->send(new MigrationFailed($e, $e->getMessage()));
|
||||
\Mail::to($user)->send(new MigrationFailed($e, $company));
|
||||
|
||||
if (app()->environment() !== 'production') {
|
||||
info($e->getMessage());
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use DirectoryIterator;
|
||||
use Faker\Factory;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
@ -44,8 +43,6 @@ class OpenApiYaml extends Command
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->faker = Factory::create();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
@ -82,6 +79,7 @@ class OpenApiYaml extends Command
|
||||
Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components.yaml'));
|
||||
|
||||
Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components/responses.yaml'));
|
||||
Storage::disk('base')->append('/openapi/api-docs.yaml', file_get_contents($path.'/components/examples.yaml'));
|
||||
|
||||
$directory = new DirectoryIterator($path . '/components/responses/');
|
||||
|
||||
|
@ -62,12 +62,13 @@ class PostUpdate extends Command
|
||||
info('finished running composer install ');
|
||||
|
||||
try {
|
||||
Artisan::call('optimize');
|
||||
// Artisan::call('optimize');
|
||||
Artisan::call('config:clear');
|
||||
} catch (\Exception $e) {
|
||||
info("I wasn't able to optimize.");
|
||||
info("I wasn't able to clear config.");
|
||||
}
|
||||
|
||||
info('optimized');
|
||||
info('cleared config');
|
||||
|
||||
try {
|
||||
Artisan::call('view:clear');
|
||||
|
@ -47,7 +47,6 @@ class S3Cleanup extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
@ -57,7 +57,6 @@ class SendRemindersCron extends Command
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@ -175,6 +174,9 @@ class SendRemindersCron extends Command
|
||||
$invoice->calc()->getInvoice()->save();
|
||||
$invoice->fresh();
|
||||
$invoice->service()->deletePdf()->save();
|
||||
if ($invoice->client->getSetting('enable_e_invoice')){
|
||||
$invoice->service()->deleteEInvoice()->save();
|
||||
}
|
||||
|
||||
/* Refresh the client here to ensure the balance is fresh */
|
||||
$client = $invoice->client;
|
||||
|
@ -51,10 +51,13 @@ class TranslationsExport extends Command
|
||||
'fi',
|
||||
'fr',
|
||||
'fr_CA',
|
||||
'fr_CH',
|
||||
'he',
|
||||
'hr',
|
||||
'hu',
|
||||
'it',
|
||||
'ja',
|
||||
'km_KH',
|
||||
'lt',
|
||||
'lv_LV',
|
||||
'mk_MK',
|
||||
@ -134,7 +137,6 @@ class TranslationsExport extends Command
|
||||
Storage::disk('local')->makeDirectory("lang/{$lang}");
|
||||
|
||||
$translations = Lang::getLoader()->load($lang, 'texts');
|
||||
|
||||
Storage::disk('local')->put("lang/{$lang}/{$lang}.json", json_encode(Arr::dot($translations), JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use App\Jobs\Cron\AutoBillCron;
|
||||
use App\Jobs\Cron\RecurringExpensesCron;
|
||||
use App\Jobs\Cron\RecurringInvoicesCron;
|
||||
use App\Jobs\Cron\SubscriptionCron;
|
||||
use App\Jobs\Cron\UpdateCalculatedFields;
|
||||
use App\Jobs\Invoice\InvoiceCheckLateWebhook;
|
||||
use App\Jobs\Ninja\AdjustEmailQuota;
|
||||
use App\Jobs\Ninja\BankTransactionSync;
|
||||
@ -47,14 +48,23 @@ class Kernel extends ConsoleKernel
|
||||
/* Check for the latest version of Invoice Ninja */
|
||||
$schedule->job(new VersionCheck)->daily();
|
||||
|
||||
/* Checks and cleans redundant files */
|
||||
$schedule->job(new DiskCleanup)->dailyAt('02:10')->withoutOverlapping()->name('disk-cleanup-job')->onOneServer();
|
||||
/* Returns the number of jobs in the queue */
|
||||
$schedule->job(new QueueSize)->everyFiveMinutes()->withoutOverlapping()->name('queue-size-job')->onOneServer();
|
||||
|
||||
/* Send reminders */
|
||||
$schedule->job(new ReminderJob)->hourly()->withoutOverlapping()->name('reminder-job')->onOneServer();
|
||||
|
||||
/* Returns the number of jobs in the queue */
|
||||
$schedule->job(new QueueSize)->everyFiveMinutes()->withoutOverlapping()->name('queue-size-job')->onOneServer();
|
||||
/* Sends recurring invoices*/
|
||||
$schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping()->name('recurring-invoice-job')->onOneServer();
|
||||
|
||||
/* Checks for scheduled tasks */
|
||||
$schedule->job(new TaskScheduler())->hourlyAt(10)->withoutOverlapping()->name('task-scheduler-job')->onOneServer();
|
||||
|
||||
/* Stale Invoice Cleanup*/
|
||||
$schedule->job(new CleanStaleInvoiceOrder)->hourlyAt(30)->withoutOverlapping()->name('stale-invoice-job')->onOneServer();
|
||||
|
||||
/* Stale Invoice Cleanup*/
|
||||
$schedule->job(new UpdateCalculatedFields)->hourlyAt(40)->withoutOverlapping()->name('update-calculated-fields-job')->onOneServer();
|
||||
|
||||
/* Checks for large companies and marked them as is_large */
|
||||
$schedule->job(new CompanySizeCheck)->dailyAt('23:20')->withoutOverlapping()->name('company-size-job')->onOneServer();
|
||||
@ -65,33 +75,26 @@ class Kernel extends ConsoleKernel
|
||||
/* Runs cleanup code for subscriptions */
|
||||
$schedule->job(new SubscriptionCron)->dailyAt('00:01')->withoutOverlapping()->name('subscription-job')->onOneServer();
|
||||
|
||||
/* Sends recurring invoices*/
|
||||
$schedule->job(new RecurringInvoicesCron)->hourly()->withoutOverlapping()->name('recurring-invoice-job')->onOneServer();
|
||||
|
||||
/* Stale Invoice Cleanup*/
|
||||
$schedule->job(new CleanStaleInvoiceOrder)->hourlyAt(30)->withoutOverlapping()->name('stale-invoice-job')->onOneServer();
|
||||
|
||||
/* Sends recurring invoices*/
|
||||
$schedule->job(new RecurringExpensesCron)->dailyAt('00:10')->withoutOverlapping()->name('recurring-expense-job')->onOneServer();
|
||||
|
||||
/* Fires notifications for expired Quotes */
|
||||
$schedule->job(new QuoteCheckExpired)->dailyAt('05:10')->withoutOverlapping()->name('quote-expired-job')->onOneServer();
|
||||
|
||||
/* Fires webhooks for overdue Invoice */
|
||||
$schedule->job(new InvoiceCheckLateWebhook)->dailyAt('07:00')->withoutOverlapping()->name('invoice-overdue-job')->onOneServer();
|
||||
|
||||
/* Performs auto billing */
|
||||
$schedule->job(new AutoBillCron)->dailyAt('06:20')->withoutOverlapping()->name('auto-bill-job')->onOneServer();
|
||||
|
||||
/* Checks the status of the scheduler */
|
||||
$schedule->job(new SchedulerCheck)->dailyAt('01:10')->withoutOverlapping();
|
||||
|
||||
/* Checks for scheduled tasks */
|
||||
$schedule->job(new TaskScheduler())->hourlyAt(10)->withoutOverlapping()->name('task-scheduler-job')->onOneServer();
|
||||
/* Checks and cleans redundant files */
|
||||
$schedule->job(new DiskCleanup)->dailyAt('02:10')->withoutOverlapping()->name('disk-cleanup-job')->onOneServer();
|
||||
|
||||
/* Performs system maintenance such as pruning the backup table */
|
||||
$schedule->job(new SystemMaintenance)->sundays()->at('02:30')->withoutOverlapping()->name('system-maintenance-job')->onOneServer();
|
||||
|
||||
/* Fires notifications for expired Quotes */
|
||||
$schedule->job(new QuoteCheckExpired)->dailyAt('05:10')->withoutOverlapping()->name('quote-expired-job')->onOneServer();
|
||||
|
||||
/* Performs auto billing */
|
||||
$schedule->job(new AutoBillCron)->dailyAt('06:20')->withoutOverlapping()->name('auto-bill-job')->onOneServer();
|
||||
|
||||
/* Fires webhooks for overdue Invoice */
|
||||
$schedule->job(new InvoiceCheckLateWebhook)->dailyAt('07:00')->withoutOverlapping()->name('invoice-overdue-job')->onOneServer();
|
||||
|
||||
if (Ninja::isSelfHost()) {
|
||||
$schedule->call(function () {
|
||||
@ -106,9 +109,6 @@ class Kernel extends ConsoleKernel
|
||||
/* Pulls in bank transactions from third party services */
|
||||
$schedule->job(new BankTransactionSync)->dailyAt('04:10')->withoutOverlapping()->name('bank-trans-sync-job')->onOneServer();
|
||||
|
||||
//not used @deprecate
|
||||
// $schedule->job(new SendFailedEmails)->daily()->withoutOverlapping();
|
||||
|
||||
$schedule->command('ninja:check-data --database=db-ninja-01')->dailyAt('02:10')->withoutOverlapping()->name('check-data-db-1-job')->onOneServer();
|
||||
|
||||
$schedule->command('ninja:check-data --database=db-ninja-02')->dailyAt('02:20')->withoutOverlapping()->name('check-data-db-2-job')->onOneServer();
|
||||
|
@ -37,7 +37,7 @@ class AccountCreated extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class AccountDeleted extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class AccountPlatform extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class AccountSignup extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class BankAccountsCreated extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class DbQuery extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class EmailCount extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class EmailFailure extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class EmailInvoiceFailure extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class EmailSuccess extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class LivePreview extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class LoginFailure extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class LoginSuccess extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class EmailBounce extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class EmailSpam extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class MigrationFailure extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class QueueSize extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class SendRecurringFailure extends GenericMixedMetric
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class TrialFinished extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class TrialStarted extends GenericCounter
|
||||
*
|
||||
* date("Y-m-d H:i:s")
|
||||
*
|
||||
* @var DateTime
|
||||
* @var \DateTime
|
||||
*/
|
||||
public $datetime;
|
||||
|
||||
|
@ -475,7 +475,16 @@ class CompanySettings extends BaseSettings
|
||||
|
||||
public $sync_invoice_quote_columns = true;
|
||||
|
||||
public $e_invoice_type = 'EN16931';
|
||||
|
||||
public $default_expense_payment_type_id = '0';
|
||||
|
||||
public $enable_e_invoice = false;
|
||||
|
||||
public static $casts = [
|
||||
'enable_e_invoice' => 'bool',
|
||||
'default_expense_payment_type_id' => 'string',
|
||||
'e_invoice_type' => 'string',
|
||||
'mailgun_endpoint' => 'string',
|
||||
'client_initiated_payments' => 'bool',
|
||||
'client_initiated_payments_minimum' => 'float',
|
||||
@ -962,6 +971,12 @@ class CompanySettings extends BaseSettings
|
||||
'$method',
|
||||
'$statement_amount',
|
||||
],
|
||||
'statement_credit_columns' => [
|
||||
'$credit.number',
|
||||
'$credit.date',
|
||||
'$total',
|
||||
'$credit.balance',
|
||||
],
|
||||
];
|
||||
|
||||
return json_decode(json_encode($variables));
|
||||
|
73
app/DataMapper/Schedule/EmailReport.php
Normal file
73
app/DataMapper/Schedule/EmailReport.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?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\Schedule;
|
||||
|
||||
class EmailReport
|
||||
{
|
||||
/**
|
||||
* Defines the template name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $template = 'email_report';
|
||||
|
||||
/**
|
||||
* An array of clients hashed_ids
|
||||
*
|
||||
* Leave blank if this action should apply to all clients
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public array $clients = [];
|
||||
|
||||
/**
|
||||
* The consts to be used to define the date_range variable of the statement
|
||||
*/
|
||||
public const LAST7 = "last7_days";
|
||||
public const LAST30 = "last30_days";
|
||||
public const LAST365 = "last365_days";
|
||||
public const THIS_MONTH = "this_month";
|
||||
public const LAST_MONTH = "last_month";
|
||||
public const THIS_QUARTER = "this_quarter";
|
||||
public const LAST_QUARTER = "last_quarter";
|
||||
public const THIS_YEAR = "this_year";
|
||||
public const LAST_YEAR = "last_year";
|
||||
public const CUSTOM_RANGE = "custom";
|
||||
|
||||
|
||||
/**
|
||||
* The date range the statement should include
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $date_range = 'this_month';
|
||||
|
||||
/**
|
||||
* If a custom range is select for the date range then
|
||||
* the start_date should be supplied in Y-m-d format
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $start_date = '';
|
||||
|
||||
/**
|
||||
* If a custom range is select for the date range then
|
||||
* the end_date should be supplied in Y-m-d format
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public string $end_date = '';
|
||||
|
||||
/** @var string $report_name */
|
||||
|
||||
public string $report_name = '';
|
||||
}
|
@ -41,6 +41,7 @@ class EmailStatement
|
||||
public const LAST_QUARTER = "last_quarter";
|
||||
public const THIS_YEAR = "this_year";
|
||||
public const LAST_YEAR = "last_year";
|
||||
public const ALL_TIME = "all_time";
|
||||
public const CUSTOM_RANGE = "custom";
|
||||
|
||||
|
||||
|
44
app/DataMapper/Tax/AT/Rule.php
Normal file
44
app/DataMapper/Tax/AT/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\AT;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'USt';
|
||||
|
||||
}
|
260
app/DataMapper/Tax/AU/Rule.php
Normal file
260
app/DataMapper/Tax/AU/Rule.php
Normal file
@ -0,0 +1,260 @@
|
||||
<?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\AU;
|
||||
|
||||
use App\DataMapper\Tax\BaseRule;
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
use App\Models\Product;
|
||||
|
||||
class Rule extends BaseRule implements RuleInterface
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'AU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
/**
|
||||
* Initializes the rules and builds any required data.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function init(): self
|
||||
{
|
||||
$this->calculateRates();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the correct tax rate based on the product type.
|
||||
*
|
||||
* @param mixed $item
|
||||
* @return self
|
||||
*/
|
||||
public function taxByType($item): self
|
||||
{
|
||||
|
||||
if ($this->client->is_tax_exempt) {
|
||||
return $this->taxExempt($item);
|
||||
}
|
||||
|
||||
match(intval($item->tax_id)) {
|
||||
Product::PRODUCT_TYPE_EXEMPT => $this->taxExempt($item),
|
||||
Product::PRODUCT_TYPE_DIGITAL => $this->taxDigital($item),
|
||||
Product::PRODUCT_TYPE_SERVICE => $this->taxService($item),
|
||||
Product::PRODUCT_TYPE_SHIPPING => $this->taxShipping($item),
|
||||
Product::PRODUCT_TYPE_PHYSICAL => $this->taxPhysical($item),
|
||||
Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced($item),
|
||||
Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override($item),
|
||||
Product::PRODUCT_TYPE_ZERO_RATED => $this->zeroRated($item),
|
||||
Product::PRODUCT_TYPE_REVERSE_TAX => $this->reverseTax($item),
|
||||
default => $this->default($item),
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a reduced tax product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function reverseTax($item): self
|
||||
{
|
||||
$this->tax_rate1 = 10;
|
||||
$this->tax_name1 = 'GST';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a reduced tax product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxReduced($item): self
|
||||
{
|
||||
$this->tax_rate1 = $this->reduced_tax_rate;
|
||||
$this->tax_name1 = 'GST';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a zero rated tax product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function zeroRated($item): self
|
||||
{
|
||||
$this->tax_rate1 = 0;
|
||||
$this->tax_name1 = 'GST';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a tax exempt product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxExempt($item): self
|
||||
{
|
||||
$this->tax_name1 = '';
|
||||
$this->tax_rate1 = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a digital product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxDigital($item): self
|
||||
{
|
||||
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
$this->tax_name1 = 'GST';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a service product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxService($item): self
|
||||
{
|
||||
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
$this->tax_name1 = 'GST';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a shipping product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxShipping($item): self
|
||||
{
|
||||
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
$this->tax_name1 = 'GST';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a physical product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxPhysical($item): self
|
||||
{
|
||||
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
$this->tax_name1 = 'GST';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a default product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function default($item): self
|
||||
{
|
||||
|
||||
$this->tax_name1 = '';
|
||||
$this->tax_rate1 = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for an override product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function override($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rates based on the client's location.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function calculateRates(): self
|
||||
{
|
||||
if ($this->client->is_tax_exempt) {
|
||||
|
||||
$this->tax_rate = 0;
|
||||
$this->reduced_tax_rate = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
// } elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->has_valid_vat_number && $this->eu_business_tax_exempt) {
|
||||
// nlog("euro zone and tax exempt");
|
||||
// $this->tax_rate = 0;
|
||||
// $this->reduced_tax_rate = 0;
|
||||
// } elseif(!in_array($this->client_subregion, $this->eu_country_codes) && ($this->foreign_consumer_tax_exempt || $this->foreign_business_tax_exempt)) { //foreign + tax exempt
|
||||
// nlog("foreign and tax exempt");
|
||||
// $this->tax_rate = 0;
|
||||
// $this->reduced_tax_rate = 0;
|
||||
// } elseif(!in_array($this->client_subregion, $this->eu_country_codes)) {
|
||||
// $this->defaultForeign();
|
||||
// } elseif(in_array($this->client_subregion, $this->eu_country_codes) && !$this->client->has_valid_vat_number) { //eu country / no valid vat
|
||||
// if(($this->client->company->tax_data->seller_subregion != $this->client_subregion) && $this->client->company->tax_data->regions->EU->has_sales_above_threshold) {
|
||||
// nlog("eu zone with sales above threshold");
|
||||
// $this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->tax_rate;
|
||||
// $this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_tax_rate;
|
||||
// } else {
|
||||
// nlog("EU with intra-community supply ie DE to DE");
|
||||
// $this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
|
||||
// $this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
|
||||
// }
|
||||
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->AU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->AU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
}
|
44
app/DataMapper/Tax/BE/Rule.php
Normal file
44
app/DataMapper/Tax/BE/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\BE;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'BTW';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/BG/Rule.php
Normal file
44
app/DataMapper/Tax/BG/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\BG;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'НДС';
|
||||
|
||||
}
|
@ -11,8 +11,11 @@
|
||||
|
||||
namespace App\DataMapper\Tax;
|
||||
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
use App\Models\Client;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Product;
|
||||
use App\DataProviders\USStates;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
|
||||
class BaseRule implements RuleInterface
|
||||
{
|
||||
@ -27,42 +30,79 @@ class BaseRule implements RuleInterface
|
||||
|
||||
public bool $foreign_consumer_tax_exempt = true;
|
||||
|
||||
public string $seller_region = '';
|
||||
|
||||
public string $client_region = '';
|
||||
|
||||
public string $client_subregion = '';
|
||||
|
||||
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
|
||||
'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 array $region_codes = [
|
||||
'AT' => 'EU', // Austria
|
||||
'BE' => 'EU', // Belgium
|
||||
'BG' => 'EU', // Bulgaria
|
||||
'CY' => 'EU', // Cyprus
|
||||
'CZ' => 'EU', // Czech Republic
|
||||
'DE' => 'EU', // Germany
|
||||
'DK' => 'EU', // Denmark
|
||||
'EE' => 'EU', // Estonia
|
||||
'ES' => 'EU', // Spain
|
||||
'FI' => 'EU', // Finland
|
||||
'FR' => 'EU', // France
|
||||
'GR' => 'EU', // Greece
|
||||
'HR' => 'EU', // Croatia
|
||||
'HU' => 'EU', // Hungary
|
||||
'IE' => 'EU', // Ireland
|
||||
'IT' => 'EU', // Italy
|
||||
'LT' => 'EU', // Lithuania
|
||||
'LU' => 'EU', // Luxembourg
|
||||
'LV' => 'EU', // Latvia
|
||||
'MT' => 'EU', // Malta
|
||||
'NL' => 'EU', // Netherlands
|
||||
'PL' => 'EU', // Poland
|
||||
'PT' => 'EU', // Portugal
|
||||
'RO' => 'EU', // Romania
|
||||
'SE' => 'EU', // Sweden
|
||||
'SI' => 'EU', // Slovenia
|
||||
'SK' => 'EU', // Slovakia
|
||||
|
||||
'US' => 'US', // United States
|
||||
|
||||
'AU' => 'AU', // Australia
|
||||
];
|
||||
|
||||
/** EU TAXES */
|
||||
|
||||
|
||||
/** US TAXES */
|
||||
/** US TAXES */
|
||||
|
||||
public string $tax_name1 = '';
|
||||
public float $tax_rate1 = 0;
|
||||
|
||||
@ -74,7 +114,11 @@ class BaseRule implements RuleInterface
|
||||
|
||||
protected ?Client $client;
|
||||
|
||||
protected ?Response $tax_data;
|
||||
public ?Response $tax_data;
|
||||
|
||||
public mixed $invoice;
|
||||
|
||||
private bool $should_calc_tax = true;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@ -84,67 +128,240 @@ class BaseRule implements RuleInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setClient(Client $client): self
|
||||
|
||||
public function shouldCalcTax(): bool
|
||||
{
|
||||
$this->client = $client;
|
||||
return $this->should_calc_tax;
|
||||
}
|
||||
/**
|
||||
* Initializes the tax rule for the entity.
|
||||
*
|
||||
* @param mixed $invoice
|
||||
* @return self
|
||||
*/
|
||||
public function setEntity(mixed $invoice): self
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
|
||||
$this->client = $invoice->client;
|
||||
|
||||
$this->resolveRegions();
|
||||
|
||||
if(!$this->isTaxableRegion())
|
||||
return $this;
|
||||
|
||||
$this->configTaxData();
|
||||
|
||||
$this->tax_data = new Response($this->invoice->tax_data);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTaxData(Response $tax_data): self
|
||||
|
||||
/**
|
||||
* Configigures the Tax Data for the entity
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function configTaxData(): self
|
||||
{
|
||||
$this->tax_data = $tax_data;
|
||||
/* We should only apply taxes for configured states */
|
||||
if(!array_key_exists($this->client->country->iso_3166_2, $this->region_codes)) {
|
||||
nlog('Automatic tax calculations not supported for this country - defaulting to company country');
|
||||
nlog("With new logic, we should never see this");
|
||||
}
|
||||
|
||||
/** Harvest the client_region */
|
||||
|
||||
/** If the tax data is already set and the invoice is marked as sent, do not adjust the rates */
|
||||
if($this->invoice->tax_data && $this->invoice->status_id > 1)
|
||||
return $this;
|
||||
|
||||
/**
|
||||
* Origin - Company Tax Data
|
||||
* Destination - Client Tax Data
|
||||
*
|
||||
*/
|
||||
|
||||
$tax_data = false;
|
||||
|
||||
if($this->seller_region == 'US' && $this->client_region == 'US'){
|
||||
|
||||
$company = $this->invoice->company;
|
||||
|
||||
/** If no company tax data has been configured, lets do that now. */
|
||||
/** We should never encounter this scenario */
|
||||
if(!$company->origin_tax_data)
|
||||
{
|
||||
$this->should_calc_tax = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** If we are in a Origin based state, force the company tax here */
|
||||
if($company->origin_tax_data?->originDestination == 'O' && ($company->tax_data?->seller_subregion == $this->client_subregion)) {
|
||||
|
||||
$tax_data = $company->origin_tax_data;
|
||||
|
||||
}
|
||||
elseif($this->client->tax_data){
|
||||
|
||||
$tax_data = $this->client->tax_data;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Applies the tax data to the invoice */
|
||||
if($this->invoice instanceof Invoice && $tax_data) {
|
||||
|
||||
$this->invoice->tax_data = $tax_data;
|
||||
|
||||
if(\DB::transactionLevel() == 0)
|
||||
$this->invoice->saveQuietly();
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolve Regions & Subregions
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function resolveRegions(): self
|
||||
{
|
||||
|
||||
$this->client_region = $this->region_codes[$this->client->country->iso_3166_2];
|
||||
|
||||
match($this->client_region){
|
||||
'US' => $this->client_subregion = isset($this->invoice?->client?->tax_data?->geoState) ? $this->invoice->client->tax_data->geoState : $this->getUSState(),
|
||||
'EU' => $this->client_subregion = $this->client->country->iso_3166_2,
|
||||
'AU' => $this->client_subregion = 'AU',
|
||||
default => $this->client_subregion = $this->client->country->iso_3166_2,
|
||||
};
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
private function getUSState(): string
|
||||
{
|
||||
try {
|
||||
|
||||
$states = USStates::$states;
|
||||
|
||||
if(isset($states[$this->client->state]))
|
||||
return $this->client->state;
|
||||
|
||||
return USStates::getState(strlen($this->client->postal_code) > 1 ? $this->client->postal_code : $this->client->shipping_postal_code);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return $this->client->company->country()->iso_3166_2 == 'US' ? $this->client->company->tax_data->seller_subregion : 'CA';
|
||||
}
|
||||
}
|
||||
|
||||
public function isTaxableRegion(): bool
|
||||
{
|
||||
return $this->client->company->tax_data->regions->{$this->client_region}->tax_all_subregions ||
|
||||
(property_exists($this->client->company->tax_data->regions->{$this->client_region}->subregions, $this->client_subregion) && $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->apply_tax);
|
||||
}
|
||||
|
||||
public function defaultForeign(): self
|
||||
{
|
||||
|
||||
if($this->client_region == 'US' && isset($this->tax_data?->taxSales)) {
|
||||
|
||||
$this->tax_rate1 = $this->tax_data->taxSales * 100;
|
||||
$this->tax_name1 = "{$this->tax_data->geoState} Sales Tax";
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
elseif($this->client_region == 'AU'){ //these are defaults and are only stubbed out for now, for AU we can actually remove these
|
||||
|
||||
$this->tax_rate1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_rate;
|
||||
$this->tax_name1 = $this->client->company->tax_data->regions->AU->subregions->AU->tax_name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
if(isset($this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion})) {
|
||||
$this->tax_rate1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_rate;
|
||||
$this->tax_name1 = $this->client->company->tax_data->regions->{$this->client_region}->subregions->{$this->client_subregion}->tax_name;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function tax($product_tax_type): self
|
||||
public function tax($item = null): self
|
||||
{
|
||||
|
||||
if ($this->client->is_tax_exempt) {
|
||||
|
||||
return $this->taxExempt($item);
|
||||
|
||||
} elseif($this->client_region == $this->seller_region && $this->isTaxableRegion()) {
|
||||
|
||||
$this->taxByType($item);
|
||||
|
||||
return $this;
|
||||
|
||||
} elseif($this->isTaxableRegion()) { //other regions outside of US
|
||||
|
||||
match(intval($item->tax_id)) {
|
||||
Product::PRODUCT_TYPE_EXEMPT => $this->taxExempt($item),
|
||||
Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced($item),
|
||||
Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override($item),
|
||||
default => $this->defaultForeign(),
|
||||
};
|
||||
|
||||
}
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function taxByType(mixed $type): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxByType($product_tax_type): self
|
||||
public function taxReduced($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxReduced(): self
|
||||
public function taxExempt($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxExempt(): self
|
||||
public function taxDigital($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxDigital(): self
|
||||
public function taxService($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxService(): self
|
||||
public function taxShipping($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxShipping(): self
|
||||
public function taxPhysical($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxPhysical(): self
|
||||
public function default($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function default(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function override(): self
|
||||
public function override($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
@ -153,4 +370,10 @@ class BaseRule implements RuleInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function regionWithNoTaxCoverage(string $iso_3166_2): bool
|
||||
{
|
||||
return ! in_array($iso_3166_2, array_merge($this->eu_country_codes, array_keys($this->region_codes)));
|
||||
}
|
||||
|
||||
}
|
||||
|
44
app/DataMapper/Tax/CY/Rule.php
Normal file
44
app/DataMapper/Tax/CY/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\CY;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'ΦΠΑ';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/CZ/Rule.php
Normal file
44
app/DataMapper/Tax/CZ/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\CZ;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'DPH';
|
||||
|
||||
}
|
@ -11,168 +11,186 @@
|
||||
|
||||
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';
|
||||
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
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;
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
public string $tax_name3 = '';
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'MwSt.';
|
||||
/**
|
||||
* Initializes the rules and builds any required data.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
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
|
||||
|
||||
/**
|
||||
* Sets the correct tax rate based on the product type.
|
||||
*
|
||||
* @param mixed $item
|
||||
* @return self
|
||||
*/
|
||||
public function taxByType($item): self
|
||||
{
|
||||
|
||||
if ($this->client->is_tax_exempt) {
|
||||
return $this->taxExempt();
|
||||
return $this->taxExempt($item);
|
||||
}
|
||||
|
||||
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(),
|
||||
match(intval($item->tax_id)){
|
||||
Product::PRODUCT_TYPE_EXEMPT => $this->taxExempt($item),
|
||||
Product::PRODUCT_TYPE_DIGITAL => $this->taxDigital($item),
|
||||
Product::PRODUCT_TYPE_SERVICE => $this->taxService($item),
|
||||
Product::PRODUCT_TYPE_SHIPPING => $this->taxShipping($item),
|
||||
Product::PRODUCT_TYPE_PHYSICAL => $this->taxPhysical($item),
|
||||
Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced($item),
|
||||
Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override($item),
|
||||
Product::PRODUCT_TYPE_ZERO_RATED => $this->zeroRated($item),
|
||||
Product::PRODUCT_TYPE_REVERSE_TAX => $this->reverseTax($item),
|
||||
default => $this->default($item),
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxReduced(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a reduced tax product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function reverseTax($item): self
|
||||
{
|
||||
$this->tax_rate1 = $this->reduced_vat_rate;
|
||||
$this->tax_name1 = 'ermäßigte MwSt.';
|
||||
$this->tax_rate1 = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxExempt(): self
|
||||
/**
|
||||
* Calculates the tax rate for a reduced tax product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxReduced($item): self
|
||||
{
|
||||
$this->tax_rate1 = $this->reduced_tax_rate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a zero rated tax product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function zeroRated($item): self
|
||||
{
|
||||
$this->tax_rate1 = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a tax exempt product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxExempt($item): self
|
||||
{
|
||||
$this->tax_name1 = '';
|
||||
$this->tax_rate1 = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxDigital(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a digital product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxDigital($item): self
|
||||
{
|
||||
$this->tax();
|
||||
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxService(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a service product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxService($item): self
|
||||
{
|
||||
$this->tax();
|
||||
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxShipping(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a shipping product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxShipping($item): self
|
||||
{
|
||||
$this->tax();
|
||||
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxPhysical(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a physical product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxPhysical($item): self
|
||||
{
|
||||
$this->tax();
|
||||
|
||||
$this->tax_rate1 = $this->tax_rate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function default(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a default product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function default($item): self
|
||||
{
|
||||
|
||||
$this->tax_name1 = '';
|
||||
@ -180,54 +198,68 @@ class Rule extends BaseRule implements RuleInterface
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function override(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for an override product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function override($item): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the tax rates based on the client's location.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function calculateRates(): self
|
||||
{
|
||||
|
||||
if ($this->client->is_tax_exempt) {
|
||||
$this->vat_rate = 0;
|
||||
$this->reduced_vat_rate = 0;
|
||||
// nlog("tax exempt");
|
||||
$this->tax_rate = 0;
|
||||
$this->reduced_tax_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)
|
||||
elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $this->eu_country_codes) && $this->client->vat_number && $this->eu_business_tax_exempt)
|
||||
// elseif($this->client_subregion != $this->client->company->tax_data->seller_subregion && in_array($this->client_subregion, $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");
|
||||
$this->tax_rate = 0;
|
||||
$this->reduced_tax_rate = 0;
|
||||
}
|
||||
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
|
||||
elseif(!in_array($this->client_subregion, $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");
|
||||
$this->tax_rate = 0;
|
||||
$this->reduced_tax_rate = 0;
|
||||
}
|
||||
elseif(in_array(strtoupper($this->client_country_code), $this->eu_country_codes) && !$this->client->has_valid_vat_number) //eu country / no valid vat
|
||||
elseif(!in_array($this->client_subregion, $this->eu_country_codes))
|
||||
{
|
||||
$this->defaultForeign();
|
||||
}
|
||||
elseif(in_array($this->client_subregion, $this->eu_country_codes) && !$this->client->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)
|
||||
if(($this->client->company->tax_data->seller_subregion != $this->client_subregion) && $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");
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->tax_rate;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->country->iso_3166_2}->reduced_tax_rate;
|
||||
}
|
||||
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");
|
||||
// nlog("EU with intra-community supply ie DE to DE");
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
|
||||
}
|
||||
}
|
||||
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");
|
||||
$this->tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->tax_rate;
|
||||
$this->reduced_tax_rate = $this->client->company->tax_data->regions->EU->subregions->{$this->client->company->country()->iso_3166_2}->reduced_tax_rate;
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
44
app/DataMapper/Tax/DK/Rule.php
Normal file
44
app/DataMapper/Tax/DK/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\DK;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'Moms';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/EE/Rule.php
Normal file
44
app/DataMapper/Tax/EE/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\EE;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'KM';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/ES/Rule.php
Normal file
44
app/DataMapper/Tax/ES/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\ES;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'IVA';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/FI/Rule.php
Normal file
44
app/DataMapper/Tax/FI/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\FI;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'ALV';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/FR/Rule.php
Normal file
44
app/DataMapper/Tax/FR/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\FR;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'TVA';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/GR/Rule.php
Normal file
44
app/DataMapper/Tax/GR/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\GR;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'IVA';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/HR/Rule.php
Normal file
44
app/DataMapper/Tax/HR/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\HR;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'PDV';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/HU/Rule.php
Normal file
44
app/DataMapper/Tax/HU/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\HU;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'ÁFA';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/IE/Rule.php
Normal file
44
app/DataMapper/Tax/IE/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\IE;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'VAT';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/IT/Rule.php
Normal file
44
app/DataMapper/Tax/IT/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\IT;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'IVA';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/LT/Rule.php
Normal file
44
app/DataMapper/Tax/LT/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\LT;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'PVM';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/LU/Rule.php
Normal file
44
app/DataMapper/Tax/LU/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\LU;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'TVA';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/LV/Rule.php
Normal file
44
app/DataMapper/Tax/LV/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\LV;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'PVN';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/MT/Rule.php
Normal file
44
app/DataMapper/Tax/MT/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\MT;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'VAT';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/NL/Rule.php
Normal file
44
app/DataMapper/Tax/NL/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\NL;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'BTW';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/PT/Rule.php
Normal file
44
app/DataMapper/Tax/PT/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\PT;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'IVA';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/RO/Rule.php
Normal file
44
app/DataMapper/Tax/RO/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\RO;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'TVA';
|
||||
|
||||
}
|
@ -11,36 +11,29 @@
|
||||
|
||||
namespace App\DataMapper\Tax;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
|
||||
interface RuleInterface
|
||||
{
|
||||
public function init();
|
||||
|
||||
public function tax(mixed $type);
|
||||
public function tax($item);
|
||||
|
||||
public function taxByType($type);
|
||||
|
||||
public function taxExempt();
|
||||
public function taxExempt($item);
|
||||
|
||||
public function taxDigital();
|
||||
public function taxDigital($item);
|
||||
|
||||
public function taxService();
|
||||
public function taxService($item);
|
||||
|
||||
public function taxShipping();
|
||||
public function taxShipping($item);
|
||||
|
||||
public function taxPhysical();
|
||||
public function taxPhysical($item);
|
||||
|
||||
public function taxReduced();
|
||||
public function taxReduced($item);
|
||||
|
||||
public function default();
|
||||
public function default($item);
|
||||
|
||||
public function override();
|
||||
|
||||
public function setClient(Client $client);
|
||||
|
||||
public function setTaxData(Response $tax_data);
|
||||
public function override($item);
|
||||
|
||||
public function calculateRates();
|
||||
}
|
44
app/DataMapper/Tax/SE/Rule.php
Normal file
44
app/DataMapper/Tax/SE/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\SE;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'Moms';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/SI/Rule.php
Normal file
44
app/DataMapper/Tax/SI/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\SI;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'DDV';
|
||||
|
||||
}
|
44
app/DataMapper/Tax/SK/Rule.php
Normal file
44
app/DataMapper/Tax/SK/Rule.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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\SK;
|
||||
|
||||
use App\DataMapper\Tax\DE\Rule as DERule;
|
||||
|
||||
class Rule extends DERule
|
||||
{
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'EU';
|
||||
|
||||
/** @var bool $consumer_tax_exempt */
|
||||
public bool $consumer_tax_exempt = false;
|
||||
|
||||
/** @var bool $business_tax_exempt */
|
||||
public bool $business_tax_exempt = false;
|
||||
|
||||
/** @var bool $eu_business_tax_exempt */
|
||||
public bool $eu_business_tax_exempt = true;
|
||||
|
||||
/** @var bool $foreign_business_tax_exempt */
|
||||
public bool $foreign_business_tax_exempt = false;
|
||||
|
||||
/** @var bool $foreign_consumer_tax_exempt */
|
||||
public bool $foreign_consumer_tax_exempt = false;
|
||||
|
||||
/** @var float $tax_rate */
|
||||
public float $tax_rate = 0;
|
||||
|
||||
/** @var float $reduced_tax_rate */
|
||||
public float $reduced_tax_rate = 0;
|
||||
|
||||
public string $tax_name1 = 'DPH';
|
||||
|
||||
}
|
@ -13,12 +13,22 @@ namespace App\DataMapper\Tax;
|
||||
|
||||
class TaxModel
|
||||
{
|
||||
// public string $seller_region = 'US';
|
||||
|
||||
|
||||
/** @var string $seller_subregion */
|
||||
public string $seller_subregion = 'CA';
|
||||
|
||||
|
||||
/** @var string $version */
|
||||
public string $version = 'alpha';
|
||||
|
||||
/** @var object $regions */
|
||||
public object $regions;
|
||||
|
||||
|
||||
/**
|
||||
* __construct
|
||||
*
|
||||
* @param TaxModel $model
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(public ?TaxModel $model = null)
|
||||
{
|
||||
|
||||
@ -28,20 +38,64 @@ class TaxModel
|
||||
$this->regions = $model;
|
||||
|
||||
}
|
||||
|
||||
public function init()
|
||||
|
||||
/**
|
||||
* Initializes the rules and builds any required data.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function init(): object
|
||||
{
|
||||
$this->regions = new \stdClass();
|
||||
$this->regions->US = new \stdClass();
|
||||
$this->regions->EU = new \stdClass();
|
||||
|
||||
$this->usRegion()
|
||||
->euRegion();
|
||||
->euRegion()
|
||||
->auRegion();
|
||||
|
||||
|
||||
return $this->regions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the model for Australian Taxes
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function auRegion(): self
|
||||
{
|
||||
$this->regions->AU = new \stdClass();
|
||||
$this->regions->AU->has_sales_above_threshold = false;
|
||||
$this->regions->AU->tax_all_subregions = false;
|
||||
$this->regions->AU->tax_threshold = 75000;
|
||||
$this->auSubRegions();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the model for Australian Subregions
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function auSubRegions(): self
|
||||
{
|
||||
|
||||
$this->regions->AU->subregions = new \stdClass();
|
||||
$this->regions->AU->subregions->AU = new \stdClass();
|
||||
$this->regions->AU->subregions->AU->apply_tax = false;
|
||||
$this->regions->AU->subregions->AU->tax_rate = 10;
|
||||
$this->regions->AU->subregions->AU->tax_name = 'GST';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the model for US Taxes
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function usRegion(): self
|
||||
{
|
||||
$this->regions->US->has_sales_above_threshold = false;
|
||||
@ -50,263 +104,404 @@ class TaxModel
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the model for EU Taxes
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
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->regions->EU->tax_threshold = 10000;
|
||||
$this->euSubRegions();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the model for US States
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
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->AL->tax_rate = 4;
|
||||
$this->regions->US->subregions->AL->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->AK = new \stdClass();
|
||||
$this->regions->US->subregions->AK->apply_tax = false;
|
||||
$this->regions->US->subregions->AK->tax_rate = 0;
|
||||
$this->regions->US->subregions->AK->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->AZ = new \stdClass();
|
||||
$this->regions->US->subregions->AZ->apply_tax = false;
|
||||
$this->regions->US->subregions->AZ->tax_rate = 5.6;
|
||||
$this->regions->US->subregions->AZ->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->AR = new \stdClass();
|
||||
$this->regions->US->subregions->AR->apply_tax = false;
|
||||
$this->regions->US->subregions->AR->tax_rate = 6.5;
|
||||
$this->regions->US->subregions->AR->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->CA = new \stdClass();
|
||||
$this->regions->US->subregions->CA->apply_tax = false;
|
||||
$this->regions->US->subregions->CA->tax_rate = 7.25;
|
||||
$this->regions->US->subregions->CA->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->CO = new \stdClass();
|
||||
$this->regions->US->subregions->CO->apply_tax = false;
|
||||
$this->regions->US->subregions->CO->tax_rate = 2.9;
|
||||
$this->regions->US->subregions->CO->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->CT = new \stdClass();
|
||||
$this->regions->US->subregions->CT->apply_tax = false;
|
||||
$this->regions->US->subregions->CT->tax_rate = 6.35;
|
||||
$this->regions->US->subregions->CT->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->DE = new \stdClass();
|
||||
$this->regions->US->subregions->DE->apply_tax = false;
|
||||
$this->regions->US->subregions->DE->tax_rate = 0;
|
||||
$this->regions->US->subregions->DE->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->FL = new \stdClass();
|
||||
$this->regions->US->subregions->FL->apply_tax = false;
|
||||
$this->regions->US->subregions->FL->tax_rate = 6;
|
||||
$this->regions->US->subregions->FL->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->GA = new \stdClass();
|
||||
$this->regions->US->subregions->GA->apply_tax = false;
|
||||
$this->regions->US->subregions->GA->tax_rate = 4;
|
||||
$this->regions->US->subregions->GA->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->HI = new \stdClass();
|
||||
$this->regions->US->subregions->HI->apply_tax = false;
|
||||
$this->regions->US->subregions->HI->tax_rate = 4;
|
||||
$this->regions->US->subregions->HI->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->ID = new \stdClass();
|
||||
$this->regions->US->subregions->ID->apply_tax = false;
|
||||
$this->regions->US->subregions->ID->tax_rate = 6;
|
||||
$this->regions->US->subregions->ID->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->IL = new \stdClass();
|
||||
$this->regions->US->subregions->IL->apply_tax = false;
|
||||
$this->regions->US->subregions->IL->tax_rate = 6.25;
|
||||
$this->regions->US->subregions->IL->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->IN = new \stdClass();
|
||||
$this->regions->US->subregions->IN->apply_tax = false;
|
||||
$this->regions->US->subregions->IN->tax_rate = 7;
|
||||
$this->regions->US->subregions->IN->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->IA = new \stdClass();
|
||||
$this->regions->US->subregions->IA->apply_tax = false;
|
||||
$this->regions->US->subregions->IA->tax_rate = 6;
|
||||
$this->regions->US->subregions->IA->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->KS = new \stdClass();
|
||||
$this->regions->US->subregions->KS->apply_tax = false;
|
||||
$this->regions->US->subregions->KS->tax_rate = 6.5;
|
||||
$this->regions->US->subregions->KS->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->KY = new \stdClass();
|
||||
$this->regions->US->subregions->KY->apply_tax = false;
|
||||
$this->regions->US->subregions->KY->tax_rate = 6;
|
||||
$this->regions->US->subregions->KY->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->LA = new \stdClass();
|
||||
$this->regions->US->subregions->LA->apply_tax = false;
|
||||
$this->regions->US->subregions->LA->tax_rate = 4.45;
|
||||
$this->regions->US->subregions->LA->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->ME = new \stdClass();
|
||||
$this->regions->US->subregions->ME->apply_tax = false;
|
||||
$this->regions->US->subregions->ME->tax_rate = 5.5;
|
||||
$this->regions->US->subregions->ME->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->MD = new \stdClass();
|
||||
$this->regions->US->subregions->MD->apply_tax = false;
|
||||
$this->regions->US->subregions->MD->tax_rate = 6;
|
||||
$this->regions->US->subregions->MD->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->MA = new \stdClass();
|
||||
$this->regions->US->subregions->MA->apply_tax = false;
|
||||
$this->regions->US->subregions->MA->tax_rate = 6.25;
|
||||
$this->regions->US->subregions->MA->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->MI = new \stdClass();
|
||||
$this->regions->US->subregions->MI->apply_tax = false;
|
||||
$this->regions->US->subregions->MI->tax_rate = 6;
|
||||
$this->regions->US->subregions->MI->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->MN = new \stdClass();
|
||||
$this->regions->US->subregions->MN->apply_tax = false;
|
||||
$this->regions->US->subregions->MN->tax_rate = 6.875;
|
||||
$this->regions->US->subregions->MN->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->MS = new \stdClass();
|
||||
$this->regions->US->subregions->MS->apply_tax = false;
|
||||
$this->regions->US->subregions->MS->tax_rate = 7;
|
||||
$this->regions->US->subregions->MS->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->MO = new \stdClass();
|
||||
$this->regions->US->subregions->MO->apply_tax = false;
|
||||
$this->regions->US->subregions->MO->tax_rate = 4.225;
|
||||
$this->regions->US->subregions->MO->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->MT = new \stdClass();
|
||||
$this->regions->US->subregions->MT->apply_tax = false;
|
||||
$this->regions->US->subregions->MT->tax_rate = 0;
|
||||
$this->regions->US->subregions->MT->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->NE = new \stdClass();
|
||||
$this->regions->US->subregions->NE->apply_tax = false;
|
||||
$this->regions->US->subregions->NE->tax_rate = 5.5;
|
||||
$this->regions->US->subregions->NE->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->NV = new \stdClass();
|
||||
$this->regions->US->subregions->NV->apply_tax = false;
|
||||
$this->regions->US->subregions->NV->tax_rate = 6.85;
|
||||
$this->regions->US->subregions->NV->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->NH = new \stdClass();
|
||||
$this->regions->US->subregions->NH->apply_tax = false;
|
||||
$this->regions->US->subregions->NH->tax_rate = 0;
|
||||
$this->regions->US->subregions->NH->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->NJ = new \stdClass();
|
||||
$this->regions->US->subregions->NJ->apply_tax = false;
|
||||
$this->regions->US->subregions->NJ->tax_rate = 6.625;
|
||||
$this->regions->US->subregions->NJ->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->NM = new \stdClass();
|
||||
$this->regions->US->subregions->NM->apply_tax = false;
|
||||
$this->regions->US->subregions->NM->tax_rate = 5.125;
|
||||
$this->regions->US->subregions->NM->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->NY = new \stdClass();
|
||||
$this->regions->US->subregions->NY->apply_tax = false;
|
||||
$this->regions->US->subregions->NY->tax_rate = 4;
|
||||
$this->regions->US->subregions->NY->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->NC = new \stdClass();
|
||||
$this->regions->US->subregions->NC->apply_tax = false;
|
||||
$this->regions->US->subregions->NC->tax_rate = 4.75;
|
||||
$this->regions->US->subregions->NC->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->ND = new \stdClass();
|
||||
$this->regions->US->subregions->ND->apply_tax = false;
|
||||
$this->regions->US->subregions->ND->tax_rate = 5;
|
||||
$this->regions->US->subregions->ND->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->OH = new \stdClass();
|
||||
$this->regions->US->subregions->OH->apply_tax = false;
|
||||
$this->regions->US->subregions->OH->tax_rate = 5.75;
|
||||
$this->regions->US->subregions->OH->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->OK = new \stdClass();
|
||||
$this->regions->US->subregions->OK->apply_tax = false;
|
||||
$this->regions->US->subregions->OK->tax_rate = 4.5;
|
||||
$this->regions->US->subregions->OK->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->OR = new \stdClass();
|
||||
$this->regions->US->subregions->OR->apply_tax = false;
|
||||
$this->regions->US->subregions->OR->tax_rate = 0;
|
||||
$this->regions->US->subregions->OR->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->PA = new \stdClass();
|
||||
$this->regions->US->subregions->PA->apply_tax = false;
|
||||
$this->regions->US->subregions->PA->tax_rate = 6;
|
||||
$this->regions->US->subregions->PA->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->RI = new \stdClass();
|
||||
$this->regions->US->subregions->RI->apply_tax = false;
|
||||
$this->regions->US->subregions->RI->tax_rate = 7;
|
||||
$this->regions->US->subregions->RI->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->SC = new \stdClass();
|
||||
$this->regions->US->subregions->SC->apply_tax = false;
|
||||
$this->regions->US->subregions->SC->tax_rate = 6;
|
||||
$this->regions->US->subregions->SC->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->SD = new \stdClass();
|
||||
$this->regions->US->subregions->SD->apply_tax = false;
|
||||
$this->regions->US->subregions->SD->tax_rate = 4.5;
|
||||
$this->regions->US->subregions->SD->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->TN = new \stdClass();
|
||||
$this->regions->US->subregions->TN->apply_tax = false;
|
||||
$this->regions->US->subregions->TN->tax_rate = 7;
|
||||
$this->regions->US->subregions->TN->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->TX = new \stdClass();
|
||||
$this->regions->US->subregions->TX->apply_tax = false;
|
||||
$this->regions->US->subregions->TX->tax_rate = 6.25;
|
||||
$this->regions->US->subregions->TX->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->UT = new \stdClass();
|
||||
$this->regions->US->subregions->UT->apply_tax = false;
|
||||
$this->regions->US->subregions->UT->tax_rate = 5.95;
|
||||
$this->regions->US->subregions->UT->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->VT = new \stdClass();
|
||||
$this->regions->US->subregions->VT->apply_tax = false;
|
||||
$this->regions->US->subregions->VT->tax_rate = 6;
|
||||
$this->regions->US->subregions->VT->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->VA = new \stdClass();
|
||||
$this->regions->US->subregions->VA->apply_tax = false;
|
||||
$this->regions->US->subregions->VA->tax_rate = 5.3;
|
||||
$this->regions->US->subregions->VA->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->WA = new \stdClass();
|
||||
$this->regions->US->subregions->WA->apply_tax = false;
|
||||
$this->regions->US->subregions->WA->tax_rate = 6.5;
|
||||
$this->regions->US->subregions->WA->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->WV = new \stdClass();
|
||||
$this->regions->US->subregions->WV->apply_tax = false;
|
||||
$this->regions->US->subregions->WV->tax_rate = 6;
|
||||
$this->regions->US->subregions->WV->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->WI = new \stdClass();
|
||||
$this->regions->US->subregions->WI->apply_tax = false;
|
||||
$this->regions->US->subregions->WI->tax_rate = 5;
|
||||
$this->regions->US->subregions->WI->tax_name = 'Sales Tax';
|
||||
$this->regions->US->subregions->WY = new \stdClass();
|
||||
$this->regions->US->subregions->WY->apply_tax = false;
|
||||
$this->regions->US->subregions->WY->tax_rate = 4;
|
||||
$this->regions->US->subregions->WY->tax_name = 'Sales Tax';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the EU member countries
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
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->tax_rate = 20;
|
||||
$this->regions->EU->subregions->AT->tax_name = 'USt';
|
||||
$this->regions->EU->subregions->AT->reduced_tax_rate = 10;
|
||||
$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->tax_rate = 21;
|
||||
$this->regions->EU->subregions->BE->tax_name = 'BTW';
|
||||
$this->regions->EU->subregions->BE->reduced_tax_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->tax_rate = 20;
|
||||
$this->regions->EU->subregions->BG->tax_name = 'НДС';
|
||||
$this->regions->EU->subregions->BG->reduced_tax_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->tax_rate = 19;
|
||||
$this->regions->EU->subregions->CY->tax_name = 'ΦΠΑ';
|
||||
$this->regions->EU->subregions->CY->reduced_tax_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->tax_rate = 21;
|
||||
$this->regions->EU->subregions->CZ->tax_name = 'DPH';
|
||||
$this->regions->EU->subregions->CZ->reduced_tax_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->tax_rate = 19;
|
||||
$this->regions->EU->subregions->DE->tax_name = 'MwSt';
|
||||
$this->regions->EU->subregions->DE->reduced_tax_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->tax_rate = 25;
|
||||
$this->regions->EU->subregions->DK->tax_name = 'Moms';
|
||||
$this->regions->EU->subregions->DK->reduced_tax_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->tax_rate = 20;
|
||||
$this->regions->EU->subregions->EE->tax_name = 'KM';
|
||||
$this->regions->EU->subregions->EE->reduced_tax_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->tax_rate = 21;
|
||||
$this->regions->EU->subregions->ES->tax_name = 'IVA';
|
||||
$this->regions->EU->subregions->ES->reduced_tax_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->tax_rate = 24;
|
||||
$this->regions->EU->subregions->FI->tax_name = 'ALV';
|
||||
$this->regions->EU->subregions->FI->reduced_tax_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->tax_rate = 20;
|
||||
$this->regions->EU->subregions->FR->tax_name = 'TVA';
|
||||
$this->regions->EU->subregions->FR->reduced_tax_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->tax_rate = 20;
|
||||
// $this->regions->EU->subregions->GB->reduced_tax_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->tax_rate = 24;
|
||||
$this->regions->EU->subregions->GR->tax_name = 'ΦΠΑ';
|
||||
$this->regions->EU->subregions->GR->reduced_tax_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->tax_rate = 25;
|
||||
$this->regions->EU->subregions->HR->tax_name = 'PDV';
|
||||
$this->regions->EU->subregions->HR->reduced_tax_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->tax_rate = 27;
|
||||
$this->regions->EU->subregions->HU->tax_name = 'ÁFA';
|
||||
$this->regions->EU->subregions->HU->reduced_tax_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->tax_rate = 23;
|
||||
$this->regions->EU->subregions->IE->tax_name = 'VAT';
|
||||
$this->regions->EU->subregions->IE->reduced_tax_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->tax_rate = 22;
|
||||
$this->regions->EU->subregions->IT->tax_name = 'IVA';
|
||||
$this->regions->EU->subregions->IT->reduced_tax_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->tax_rate = 21;
|
||||
$this->regions->EU->subregions->LT->tax_name = 'PVM';
|
||||
$this->regions->EU->subregions->LT->reduced_tax_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->tax_rate = 17;
|
||||
$this->regions->EU->subregions->LU->tax_name = 'TVA';
|
||||
$this->regions->EU->subregions->LU->reduced_tax_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->tax_rate = 21;
|
||||
$this->regions->EU->subregions->LV->tax_name = 'PVN';
|
||||
$this->regions->EU->subregions->LV->reduced_tax_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->tax_rate = 18;
|
||||
$this->regions->EU->subregions->MT->tax_name = 'VAT';
|
||||
$this->regions->EU->subregions->MT->reduced_tax_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->tax_rate = 21;
|
||||
$this->regions->EU->subregions->NL->tax_name = 'BTW';
|
||||
$this->regions->EU->subregions->NL->reduced_tax_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->tax_rate = 23;
|
||||
$this->regions->EU->subregions->PT->tax_name = 'IVA';
|
||||
$this->regions->EU->subregions->PT->reduced_tax_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->tax_rate = 19;
|
||||
$this->regions->EU->subregions->RO->tax_name = 'TVA';
|
||||
$this->regions->EU->subregions->RO->reduced_tax_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->tax_rate = 25;
|
||||
$this->regions->EU->subregions->SE->tax_name = 'Moms';
|
||||
$this->regions->EU->subregions->SE->reduced_tax_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->tax_rate = 22;
|
||||
$this->regions->EU->subregions->SI->tax_name = 'DDV';
|
||||
$this->regions->EU->subregions->SI->reduced_tax_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->tax_rate = 20;
|
||||
$this->regions->EU->subregions->SK->tax_name = 'DPH';
|
||||
$this->regions->EU->subregions->SK->reduced_tax_rate = 10;
|
||||
$this->regions->EU->subregions->SK->apply_tax = false;
|
||||
|
||||
return $this;
|
||||
|
@ -11,151 +11,213 @@
|
||||
|
||||
namespace App\DataMapper\Tax\US;
|
||||
|
||||
use App\Models\Client;
|
||||
use App\Models\Product;
|
||||
use App\DataMapper\Tax\BaseRule;
|
||||
use App\DataMapper\Tax\RuleInterface;
|
||||
use App\DataMapper\Tax\ZipTax\Response;
|
||||
use App\Models\Product;
|
||||
|
||||
class Rule implements RuleInterface
|
||||
/**
|
||||
* The rules apply US => US taxes using the tax calculator.
|
||||
*
|
||||
* US => Foreign taxes we check the product types still for exemptions, and we all back to the client country tax rate.
|
||||
*/
|
||||
class Rule extends BaseRule implements RuleInterface
|
||||
{
|
||||
|
||||
public string $tax_name1 = '';
|
||||
public float $tax_rate1 = 0;
|
||||
|
||||
public string $tax_name2 = '';
|
||||
public float $tax_rate2 = 0;
|
||||
/** @var string $seller_region */
|
||||
public string $seller_region = 'US';
|
||||
|
||||
public string $tax_name3 = '';
|
||||
public float $tax_rate3 = 0;
|
||||
/**
|
||||
* Initializes the rules and builds any required data.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function init(): self
|
||||
{
|
||||
$this->calculateRates();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
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
|
||||
/**
|
||||
* Override tax class, we use this when we do not modify the input taxes
|
||||
*
|
||||
* @param mixed $item
|
||||
* @return self
|
||||
*/
|
||||
public function override($item): 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);
|
||||
$this->tax_rate1 = $item->tax_rate1;
|
||||
$this->tax_name1 = $item->tax_name1;
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function taxByType($product_tax_type): self
|
||||
|
||||
/**
|
||||
* Sets the correct tax rate based on the product type.
|
||||
*
|
||||
* @param mixed $item
|
||||
* @return self
|
||||
*/
|
||||
public function taxByType($item): 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(),
|
||||
match(intval($item->tax_id)) {
|
||||
Product::PRODUCT_TYPE_EXEMPT => $this->taxExempt($item),
|
||||
Product::PRODUCT_TYPE_DIGITAL => $this->taxDigital($item),
|
||||
Product::PRODUCT_TYPE_SERVICE => $this->taxService($item),
|
||||
Product::PRODUCT_TYPE_SHIPPING => $this->taxShipping($item),
|
||||
Product::PRODUCT_TYPE_PHYSICAL => $this->taxPhysical($item),
|
||||
Product::PRODUCT_TYPE_REDUCED_TAX => $this->taxReduced($item),
|
||||
Product::PRODUCT_TYPE_OVERRIDE_TAX => $this->override($item),
|
||||
Product::PRODUCT_TYPE_ZERO_RATED => $this->zeroRated($item),
|
||||
default => $this->default($item),
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxExempt(): self
|
||||
|
||||
/**
|
||||
* Sets the tax as exempt (0)
|
||||
* @param mixed $item
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxExempt($item): self
|
||||
{
|
||||
$this->tax_name1 = '';
|
||||
$this->tax_rate1 = 0;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxDigital(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a digital product
|
||||
* @param mixed $item
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxDigital($item): self
|
||||
{
|
||||
$this->default();
|
||||
$this->default($item);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxService(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a service product
|
||||
* @param mixed $item
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxService($item): self
|
||||
{
|
||||
if($this->tax_data->txbService == 'Y')
|
||||
$this->default();
|
||||
if(in_array($this->tax_data?->txbService,['Y','L'])) {
|
||||
$this->default($item);
|
||||
}
|
||||
else {
|
||||
$this->taxExempt($item);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxShipping(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a shipping product
|
||||
* @param mixed $item
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxShipping($item): self
|
||||
{
|
||||
if($this->tax_data->txbFreight == 'Y')
|
||||
$this->default();
|
||||
if($this->tax_data?->txbFreight == 'Y') {
|
||||
return $this->default($item);
|
||||
}
|
||||
|
||||
$this->tax_rate1 = 0;
|
||||
$this->tax_name1 = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a physical product
|
||||
* @param mixed $item
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxPhysical($item): self
|
||||
{
|
||||
$this->default($item);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxPhysical(): self
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for an undefined product uses the default tax rate for the client county
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function default($item): self
|
||||
{
|
||||
$this->default();
|
||||
|
||||
if($this->tax_data?->stateSalesTax == 0) {
|
||||
|
||||
return $this;
|
||||
}
|
||||
$this->tax_rate1 = 0;
|
||||
$this->tax_name1 = '';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function default(): self
|
||||
{
|
||||
|
||||
$this->tax_rate1 = $this->tax_data->taxSales * 100;
|
||||
$this->tax_name1 = "{$this->tax_data->geoState} Sales Tax";
|
||||
$this->tax_name1 = "Sales Tax";
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function taxReduced(): self
|
||||
|
||||
public function zeroRated($item): self
|
||||
{
|
||||
$this->default();
|
||||
|
||||
$this->tax_rate1 = 0;
|
||||
$this->tax_name1 = "{$this->tax_data->geoState} Zero Rated Tax";
|
||||
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function init(): self
|
||||
/**
|
||||
* Calculates the tax rate for a reduced tax product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function taxReduced($item): self
|
||||
{
|
||||
$this->default($item);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rate for a reverse tax product
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function reverseTax($item): self
|
||||
{
|
||||
$this->default($item);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the tax rates to be applied
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function calculateRates(): self
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -57,7 +57,7 @@ class Response
|
||||
* ];
|
||||
*
|
||||
*/
|
||||
public string $seller_region = "";
|
||||
public string $seller_subregion = "";
|
||||
//US
|
||||
|
||||
public string $geoPostalCode = "";
|
||||
@ -65,14 +65,17 @@ class Response
|
||||
public string $geoCounty = "";
|
||||
public string $geoState = "";
|
||||
public float $taxSales = 0;
|
||||
public string $taxName = "";
|
||||
public float $taxUse = 0;
|
||||
public string $txbService = ""; // N = No, Y = Yes
|
||||
public string $txbFreight = ""; // N = No, Y = Yes
|
||||
public string $txbService = "Y"; // N = No, Y = Yes
|
||||
public string $txbFreight = "Y"; // N = No, Y = Yes
|
||||
public float $stateSalesTax = 0;
|
||||
public float $stateUseTax = 0;
|
||||
public float $citySalesTax = 0;
|
||||
public float $cityUseTax = 0;
|
||||
public string $cityTaxCode = "";
|
||||
|
||||
/* US SPECIFIC TAX CODES */
|
||||
public float $countySalesTax = 0;
|
||||
public float $countyUseTax = 0;
|
||||
public string $countyTaxCode = "";
|
||||
@ -93,13 +96,19 @@ class Response
|
||||
public string $district5Code = "";
|
||||
public float $district5SalesTax = 0;
|
||||
public float $district5UseTax = 0;
|
||||
public string $originDestination = "";
|
||||
/* US SPECIFIC TAX CODES */
|
||||
|
||||
public function __construct($data)
|
||||
public string $originDestination = "D"; // defines if the client origin is the locale where the tax is remitted to
|
||||
|
||||
public function __construct($data = null)
|
||||
{
|
||||
|
||||
foreach($data as $key => $value){
|
||||
$this->{$key} = $value;
|
||||
if($data) {
|
||||
|
||||
foreach($data as $key => $value) {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -106,9 +106,8 @@ region:
|
||||
apply_tax: false
|
||||
EU:
|
||||
tax_all: false
|
||||
vat_threshold: 10000
|
||||
tax_threshold: 10000
|
||||
has_sales_above_threshold: false
|
||||
seller_region: DE
|
||||
subregions:
|
||||
AT:
|
||||
vat: 21
|
||||
|
24
app/DataProviders/DesignBlocks.php
Normal file
24
app/DataProviders/DesignBlocks.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\DataProviders;
|
||||
|
||||
class DesignBlocks
|
||||
{
|
||||
public function __construct(
|
||||
public string $includes = '',
|
||||
public string $header = '',
|
||||
public string $body = '',
|
||||
public string $footer = ''
|
||||
) {
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -24,9 +24,6 @@ class AccountCreated
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $user;
|
||||
|
||||
public $company;
|
||||
@ -47,13 +44,14 @@ class AccountCreated
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
// /**
|
||||
// * Get the channels the event should broadcast on.
|
||||
// *
|
||||
// * @return Channel|array
|
||||
// */
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
// return new PrivateChannel('channel-name');
|
||||
}
|
||||
}
|
||||
|
@ -49,13 +49,13 @@ class ClientWasArchived
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
// /**
|
||||
// * Get the channels the event should broadcast on.
|
||||
// *
|
||||
// * @return Channel|array
|
||||
// */
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ class CompanyDocumentsDeleted
|
||||
*
|
||||
* @return Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -25,9 +25,6 @@ class ContactLoggedIn
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
public $client_contact;
|
||||
|
||||
public $company;
|
||||
@ -53,8 +50,8 @@ class ContactLoggedIn
|
||||
*
|
||||
* @return Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class CreditWasEmailed
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Credit $credit
|
||||
* @param CreditInvitation $invitation
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
|
@ -23,7 +23,7 @@ class CreditWasRestored
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
* @var Credit
|
||||
*/
|
||||
public $credit;
|
||||
|
||||
|
@ -26,29 +26,8 @@ class DesignWasArchived
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Design
|
||||
*/
|
||||
public $design;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Design $design
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(Design $design, Company $company, array $event_vars)
|
||||
public function __construct(public Design $design, public Company $company, public array $event_vars)
|
||||
{
|
||||
$this->design = $design;
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,8 +35,8 @@ class DesignWasArchived
|
||||
*
|
||||
* @return Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,10 @@
|
||||
|
||||
namespace App\Events\Design;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Design;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
|
||||
/**
|
||||
* Class DesignWasCreated.
|
||||
@ -22,29 +23,8 @@ class DesignWasCreated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Design
|
||||
*/
|
||||
public $design;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Design $design
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(Design $design, Company $company, array $event_vars)
|
||||
public function __construct(public Design $design, public Company $company, public array $event_vars)
|
||||
{
|
||||
$this->design = $design;
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,8 +32,8 @@ class DesignWasCreated
|
||||
*
|
||||
* @return PrivateChannel
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,10 @@
|
||||
|
||||
namespace App\Events\Design;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Design;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
|
||||
/**
|
||||
* Class DesignWasDeleted.
|
||||
@ -22,38 +23,17 @@ class DesignWasDeleted
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Design
|
||||
*/
|
||||
public $design;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Design $design
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(Design $design, Company $company, array $event_vars)
|
||||
public function __construct(public Design $design, public Company $company, public array $event_vars)
|
||||
{
|
||||
$this->design = $design;
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return PrivateChannel
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,10 @@
|
||||
|
||||
namespace App\Events\Design;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Design;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
|
||||
/**
|
||||
* Class DesignWasRestored.
|
||||
@ -22,33 +23,8 @@ class DesignWasRestored
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Design
|
||||
*/
|
||||
public $design;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
public $fromDeleted;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Design $design
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(Design $design, $fromDeleted, Company $company, array $event_vars)
|
||||
public function __construct(public Design $design, public bool $fromDeleted, public Company $company, public array $event_vars)
|
||||
{
|
||||
$this->design = $design;
|
||||
|
||||
$this->fromDeleted = $fromDeleted;
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,8 +32,8 @@ class DesignWasRestored
|
||||
*
|
||||
* @return PrivateChannel
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,10 @@
|
||||
|
||||
namespace App\Events\Design;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Design;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
|
||||
/**
|
||||
* Class DesignWasUpdated.
|
||||
@ -22,29 +23,8 @@ class DesignWasUpdated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Design
|
||||
*/
|
||||
public $design;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Design $design
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(Design $design, Company $company, array $event_vars)
|
||||
public function __construct(public Design $design, public Company $company, public array $event_vars)
|
||||
{
|
||||
$this->design = $design;
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,8 +32,8 @@ class DesignWasUpdated
|
||||
*
|
||||
* @return PrivateChannel
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,6 @@ class DocumentWasArchived
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -22,29 +22,7 @@ class InvoiceReminderWasEmailed
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Invoice
|
||||
*/
|
||||
public $invitation;
|
||||
|
||||
public $reminder;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param InvoiceInvitation $invitation
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(InvoiceInvitation $invitation, Company $company, array $event_vars, string $reminder)
|
||||
public function __construct(public InvoiceInvitation $invitation, public Company $company, public array $event_vars, public string $template)
|
||||
{
|
||||
$this->invitation = $invitation;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
$this->reminder = $reminder;
|
||||
}
|
||||
}
|
||||
|
@ -56,17 +56,17 @@ class InvoiceWasCreated implements ShouldBroadcast
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return ['simple-channel'];
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the data to broadcast.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function broadcastWith(): array
|
||||
{
|
||||
return ['id' => 'value'];
|
||||
}
|
||||
// /**
|
||||
// * Get the data to broadcast.
|
||||
// *
|
||||
// * @return array<string, mixed>
|
||||
// */
|
||||
// public function broadcastWith(): array
|
||||
// {
|
||||
// return ['id' => 'value'];
|
||||
// }
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class InvoiceWasEmailed
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Invoice
|
||||
* @var InvoiceInvitation
|
||||
*/
|
||||
public $invitation;
|
||||
|
||||
|
@ -21,34 +21,7 @@ class InvoiceWasEmailedAndFailed
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public $invitation;
|
||||
|
||||
public $message;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
public $template;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param $invitation
|
||||
* @param Company $company
|
||||
* @param string $errors
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct($invitation, Company $company, string $message, string $template, array $event_vars)
|
||||
public function __construct(public mixed $invitation, public Company $company, public string $message, public string $template, public array $event_vars)
|
||||
{
|
||||
$this->invitation = $invitation;
|
||||
|
||||
$this->company = $company;
|
||||
|
||||
$this->message = $message;
|
||||
|
||||
$this->event_vars = $event_vars;
|
||||
|
||||
$this->template = $template;
|
||||
}
|
||||
}
|
||||
|
@ -22,14 +22,6 @@ class InvoiceWasViewed
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Invoice
|
||||
*/
|
||||
public $invitation;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
@ -38,10 +30,7 @@ class InvoiceWasViewed
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(InvoiceInvitation $invitation, Company $company, array $event_vars)
|
||||
public function __construct(public InvoiceInvitation $invitation, public Company $company, public array $event_vars)
|
||||
{
|
||||
$this->invitation = $invitation;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class MethodDeleted
|
||||
/**
|
||||
* @var ClientGatewayToken
|
||||
*/
|
||||
private $payment_method;
|
||||
public $payment_method;
|
||||
|
||||
public $company;
|
||||
|
||||
@ -51,8 +51,8 @@ class MethodDeleted
|
||||
*
|
||||
* @return Channel|array
|
||||
*/
|
||||
public function broadcastOn()
|
||||
{
|
||||
return new PrivateChannel('channel-name');
|
||||
}
|
||||
public function broadcastOn()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,10 @@ namespace App\Events\Payment;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Payment;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use App\Models\ClientContact;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
|
||||
/**
|
||||
* Class PaymentWasEmailed.
|
||||
@ -24,26 +25,15 @@ class PaymentWasEmailed
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Payment
|
||||
*/
|
||||
public $payment;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Payment $payment
|
||||
* @param Company $company
|
||||
* @param ClientContact $contact
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(Payment $payment, Company $company, array $event_vars)
|
||||
public function __construct(public Payment $payment, public Company $company, public ClientContact $contact, public array $event_vars)
|
||||
{
|
||||
$this->payment = $payment;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
||||
|
@ -19,26 +19,7 @@ class ProductWasArchived
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Product
|
||||
*/
|
||||
public $product;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Product $product
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(Product $product, Company $company, array $event_vars)
|
||||
public function __construct(public Product $product, public Company $company, public array $event_vars)
|
||||
{
|
||||
$this->product = $product;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
||||
|
@ -19,30 +19,7 @@ class ProductWasCreated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Product
|
||||
*/
|
||||
public $product;
|
||||
|
||||
public $input;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Product $product
|
||||
* @param $input
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(Product $product, $input, Company $company, array $event_vars)
|
||||
public function __construct(public Product $product, public mixed $input, public Company $company, public array $event_vars)
|
||||
{
|
||||
$this->product = $product;
|
||||
$this->input = $input;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
||||
|
@ -19,26 +19,7 @@ class ProductWasDeleted
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Product
|
||||
*/
|
||||
public $product;
|
||||
|
||||
public $company;
|
||||
|
||||
public $event_vars;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Product $product
|
||||
* @param Company $company
|
||||
* @param array $event_vars
|
||||
*/
|
||||
public function __construct(Product $product, Company $company, array $event_vars)
|
||||
public function __construct(public Product $product, public Company $company, public array $event_vars)
|
||||
{
|
||||
$this->product = $product;
|
||||
$this->company = $company;
|
||||
$this->event_vars = $event_vars;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user