mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-31 03:17:32 -04:00 
			
		
		
		
	
						commit
						9c9acd29f9
					
				
							
								
								
									
										3
									
								
								.env.ci
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								.env.ci
									
									
									
									
									
								
							| @ -23,4 +23,5 @@ API_SECRET=superdoopersecrethere | ||||
| PHANTOMJS_PDF_GENERATION=false | ||||
| CACHE_DRIVER=redis | ||||
| QUEUE_CONNECTION=redis | ||||
| SESSION_DRIVER=redis | ||||
| SESSION_DRIVER=redis | ||||
| PDF_GENERATOR=hosted_ninja | ||||
							
								
								
									
										10
									
								
								.github/workflows/react_release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/workflows/react_release.yml
									
									
									
									
										vendored
									
									
								
							| @ -44,10 +44,11 @@ jobs: | ||||
|           git clone https://${{secrets.commit_secret}}@github.com/invoiceninja/ui.git | ||||
|           cd ui | ||||
|           git checkout develop | ||||
|           cp ../vite.config.ts.react ./vite.config.js | ||||
|           npm i | ||||
|           npm run build | ||||
|           cp -r dist/* ../public/ | ||||
|           cp dist/index.html ../resources/views/react/index.blade.php | ||||
|           mv dist/index.html ../resources/views/react/index.blade.php | ||||
|            | ||||
|       - name: Prepare JS/CSS assets | ||||
|         run: | | ||||
| @ -60,11 +61,12 @@ jobs: | ||||
|           sudo rm -rf node_modules | ||||
|           sudo rm -rf .git | ||||
|           sudo rm .env | ||||
| 
 | ||||
|           sudo rm -rf ui | ||||
|            | ||||
|       - name: Build project | ||||
|         run: | | ||||
|           shopt -s dotglob | ||||
|           tar --exclude='public/storage' --exclude='./htaccess' --exclude='invoiceninja.zip' -zcvf /home/runner/work/invoiceninja/react-invoiceninja.tar * | ||||
|           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/') | ||||
| @ -72,4 +74,4 @@ jobs: | ||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
|         with: | ||||
|           files: | | ||||
|             /home/runner/work/invoiceninja/react-invoiceninja.tar | ||||
|             /home/runner/work/invoiceninja/invoiceninja.tar | ||||
							
								
								
									
										86
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										86
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @ -1,86 +0,0 @@ | ||||
| on: | ||||
|   release: | ||||
|     types: [released] | ||||
| 
 | ||||
| name: Upload Release Asset | ||||
| 
 | ||||
| jobs: | ||||
|   build: | ||||
|     name: Upload Release Asset | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Setup PHP | ||||
|         uses: shivammathur/setup-php@v2 | ||||
|         with: | ||||
|           php-version: 8.2 | ||||
|           extensions: mysql, mysqlnd, sqlite3, bcmath, gd, curl, zip, openssl, mbstring, xml | ||||
| 
 | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v1 | ||||
|         with: | ||||
|           ref: v5-develop | ||||
|        | ||||
|       - name: Copy .env file | ||||
|         run: | | ||||
|           cp .env.example .env | ||||
| 
 | ||||
|       - name: Install composer dependencies | ||||
|         run: | | ||||
|           composer config -g github-oauth.github.com ${{ secrets.GITHUB_TOKEN }} | ||||
|           composer install --no-dev | ||||
|        | ||||
|       - name: Prepare Laravel Application | ||||
|         run: | | ||||
|           cp .env.example .env | ||||
|           php artisan key:generate --force | ||||
|           php artisan optimize | ||||
|           php artisan storage:link --force | ||||
|           sudo php artisan cache:clear | ||||
|           sudo find ./vendor/bin/ -type f -exec chmod +x {} \; | ||||
|           sudo find ./ -type d -exec chmod 755 {} \; | ||||
|            | ||||
|       - name: Prepare React FrontEnd | ||||
|         run: | | ||||
|           git clone https://${{secrets.commit_secret}}@github.com/invoiceninja/ui.git | ||||
|           cd ui | ||||
|           git checkout develop | ||||
|           npm i | ||||
|           npm run build | ||||
|            | ||||
|           mkdir -p ../public/react/${{ github.event.release.tag_name }}/ | ||||
|           cp -r dist/react/* ../public/react/${{ github.event.release.tag_name }}/ | ||||
|           cp -r dist/react/* ../public/react/ | ||||
|           cp dist/index.html ../resources/views/react/index.blade.php | ||||
|            | ||||
|           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 | ||||
| 
 | ||||
|       - name: Prepare JS/CSS assets | ||||
|         run: | | ||||
|           npm i | ||||
|           npm run production | ||||
| 
 | ||||
|       - name: Cleanup Builds | ||||
|         run: | | ||||
|           sudo rm -rf bootstrap/cache/* | ||||
|           sudo rm -rf node_modules | ||||
|           sudo rm -rf .git | ||||
|           sudo rm .env | ||||
| 
 | ||||
|       - name: Build project | ||||
|         run: | | ||||
|           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/') | ||||
|         env: | ||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
|         with: | ||||
|           files: | | ||||
|             /home/runner/work/invoiceninja/invoiceninja.tar | ||||
|             /home/runner/work/invoiceninja/invoiceninja.zip | ||||
| @ -1 +1 @@ | ||||
| 5.9.2 | ||||
| 5.10.5 | ||||
| @ -176,6 +176,7 @@ class BackupUpdate extends Command | ||||
|                     try { | ||||
|                         $doc_bin = $document->getFile(); | ||||
|                     } catch(\Exception $e) { | ||||
|                         nlog("Exception:: BackupUpdate::" . $e->getMessage()); | ||||
|                         nlog($e->getMessage()); | ||||
|                     } | ||||
| 
 | ||||
| @ -184,8 +185,6 @@ class BackupUpdate extends Command | ||||
| 
 | ||||
|                         $document->disk = $this->option('disk'); | ||||
|                         $document->saveQuietly(); | ||||
| 
 | ||||
|                         nlog("Documents - Moving {$document->url} to {$this->option('disk')}"); | ||||
|                     } | ||||
|                 }); | ||||
| 
 | ||||
| @ -199,8 +198,6 @@ class BackupUpdate extends Command | ||||
| 
 | ||||
|                     if ($backup_bin) { | ||||
|                         Storage::disk($this->option('disk'))->put($backup->filename, $backup_bin); | ||||
| 
 | ||||
|                         nlog("Backups - Moving {$backup->filename} to {$this->option('disk')}"); | ||||
|                     } | ||||
|                 }); | ||||
|     } | ||||
|  | ||||
| @ -12,37 +12,38 @@ | ||||
| namespace App\Console\Commands; | ||||
| 
 | ||||
| use App; | ||||
| 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\Expense; | ||||
| use App\Models\Invoice; | ||||
| use App\Models\Payment; | ||||
| use App\Libraries\MultiDB; | ||||
| 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\RecurringInvoice; | ||||
| use App\Models\InvoiceInvitation; | ||||
| 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\Libraries\MultiDB; | ||||
| use App\Models\Account; | ||||
| use App\Models\BankTransaction; | ||||
| 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\RecurringInvoice; | ||||
| use App\Models\RecurringInvoiceInvitation; | ||||
| use App\Models\User; | ||||
| use App\Models\Vendor; | ||||
| use App\Models\VendorContact; | ||||
| use App\Utils\Ninja; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Mail; | ||||
| use Illuminate\Support\Str; | ||||
| use Symfony\Component\Console\Input\InputOption; | ||||
| 
 | ||||
| /* | ||||
| @ -130,6 +131,7 @@ class CheckData extends Command | ||||
|         $this->checkContactEmailAndSendEmailStatus(); | ||||
|         $this->checkPaymentCurrency(); | ||||
|         $this->checkSubdomainsSet(); | ||||
|         $this->checkExpenseCurrency(); | ||||
| 
 | ||||
|         if (Ninja::isHosted()) { | ||||
|             $this->checkAccountStatuses(); | ||||
| @ -172,18 +174,18 @@ class CheckData extends Command | ||||
|         CompanyUser::query()->cursor()->each(function ($cu) { | ||||
| 
 | ||||
|             if (CompanyToken::where('user_id', $cu->user_id)->where('company_id', $cu->company_id)->where('is_system', 1)->doesntExist()) { | ||||
|                  | ||||
| 
 | ||||
| 
 | ||||
|                 if ($cu->company && $cu->user) { | ||||
|                     $this->logMessage("Creating missing company token for user # {$cu->user_id} for company id # {$cu->company_id}"); | ||||
|                     (new CreateCompanyToken($cu->company, $cu->user, 'System'))->handle(); | ||||
|                 }  | ||||
|                  | ||||
|                 } | ||||
| 
 | ||||
|                 if (!$cu->user) { | ||||
|                     $this->logMessage("No user found for company user - removing company user"); | ||||
|                     $cu->forceDelete(); | ||||
|                 } | ||||
|                      | ||||
| 
 | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| @ -477,14 +479,13 @@ class CheckData extends Command | ||||
|                         } | ||||
|                     } else { | ||||
|                         $this->logMessage("No contact present, so cannot add invitation for {$entity_key} - {$entity->id}"); | ||||
|                          | ||||
|                         try{ | ||||
| 
 | ||||
|                         try { | ||||
|                             $entity->service()->createInvitations()->save(); | ||||
|                         } | ||||
|                         catch(\Exception $e){ | ||||
|                         } catch(\Exception $e) { | ||||
| 
 | ||||
|                         } | ||||
|                          | ||||
| 
 | ||||
|                     } | ||||
| 
 | ||||
|                     try { | ||||
| @ -949,12 +950,12 @@ class CheckData extends Command | ||||
| 
 | ||||
|             }); | ||||
| 
 | ||||
|             Company::whereDoesntHave('company_users', function ($query){ | ||||
|             $query->where('is_owner', 1); | ||||
|             Company::whereDoesntHave('company_users', function ($query) { | ||||
|                 $query->where('is_owner', 1); | ||||
|             }) | ||||
|             ->cursor() | ||||
|             ->when(Ninja::isHosted()) | ||||
|             ->each(function ($c){ | ||||
|             ->each(function ($c) { | ||||
| 
 | ||||
|                 $this->logMessage("Orphan Account # {$c->account_id}"); | ||||
| 
 | ||||
| @ -963,8 +964,8 @@ class CheckData extends Command | ||||
|             CompanyUser::whereDoesntHave('tokens') | ||||
|             ->cursor() | ||||
|             ->when(Ninja::isHosted()) | ||||
|             ->each(function ($cu){ | ||||
|                  | ||||
|             ->each(function ($cu) { | ||||
| 
 | ||||
|                 $this->logMessage("Missing tokens for Company User # {$cu->id}"); | ||||
| 
 | ||||
|             }); | ||||
| @ -1159,7 +1160,21 @@ class CheckData extends Command | ||||
| 
 | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function checkExpenseCurrency() | ||||
|     { | ||||
|         Expense::with('company') | ||||
|                 ->withTrashed() | ||||
|                 ->whereNull('exchange_rate') | ||||
|                 ->orWhere('exchange_rate', 0) | ||||
|                 ->cursor() | ||||
|                 ->each(function ($expense){ | ||||
|                     $expense->exchange_rate = 1; | ||||
|                     $expense->saveQuietly(); | ||||
|                      | ||||
|                     $this->logMessage("Fixing - exchange rate for expense :: {$expense->id}"); | ||||
| 
 | ||||
|                 }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -56,8 +56,6 @@ class CreateAccount extends Command | ||||
|     { | ||||
|         $this->info(date('r').' Create Single Account...'); | ||||
| 
 | ||||
|         $this->warmCache(); | ||||
| 
 | ||||
|         $this->createAccount(); | ||||
|     } | ||||
| 
 | ||||
| @ -121,28 +119,6 @@ class CreateAccount extends Command | ||||
|         (new CreateCompanyTaskStatuses($company, $user))->handle(); | ||||
|         (new VersionCheck())->handle(); | ||||
| 
 | ||||
|         $this->warmCache(); | ||||
|     } | ||||
| 
 | ||||
|     private function warmCache() | ||||
|     { | ||||
|         /* Warm up the cache !*/ | ||||
|         $cached_tables = config('ninja.cached_tables'); | ||||
| 
 | ||||
|         foreach ($cached_tables as $name => $class) { | ||||
|             if ($name == 'payment_terms') { | ||||
|                 $orderBy = 'num_days'; | ||||
|             } elseif ($name == 'fonts') { | ||||
|                 $orderBy = 'sort_order'; | ||||
|             } elseif (in_array($name, ['currencies', 'industries', 'languages', 'countries', 'banks'])) { | ||||
|                 $orderBy = 'name'; | ||||
|             } else { | ||||
|                 $orderBy = 'id'; | ||||
|             } | ||||
|             $tableData = $class::orderBy($orderBy)->get(); | ||||
|             if ($tableData->count()) { | ||||
|                 Cache::forever($name, $tableData); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -97,10 +97,6 @@ class CreateSingleAccount extends Command | ||||
|         $this->count = 5; | ||||
|         $this->gateway = $this->argument('gateway'); | ||||
| 
 | ||||
|         $this->info('Warming up cache'); | ||||
| 
 | ||||
|         $this->warmCache(); | ||||
| 
 | ||||
|         $this->createSmallAccount(); | ||||
| 
 | ||||
| 
 | ||||
| @ -774,32 +770,6 @@ class CreateSingleAccount extends Command | ||||
|         return $line_items; | ||||
|     } | ||||
| 
 | ||||
|     private function warmCache() | ||||
|     { | ||||
|         /* Warm up the cache !*/ | ||||
|         $cached_tables = config('ninja.cached_tables'); | ||||
| 
 | ||||
|         foreach ($cached_tables as $name => $class) { | ||||
|             // check that the table exists in case the migration is pending
 | ||||
|             if (! Schema::hasTable((new $class())->getTable())) { | ||||
|                 continue; | ||||
|             } | ||||
|             if ($name == 'payment_terms') { | ||||
|                 $orderBy = 'num_days'; | ||||
|             } elseif ($name == 'fonts') { | ||||
|                 $orderBy = 'sort_order'; | ||||
|             } elseif (in_array($name, ['currencies', 'industries', 'languages', 'countries', 'banks'])) { | ||||
|                 $orderBy = 'name'; | ||||
|             } else { | ||||
|                 $orderBy = 'id'; | ||||
|             } | ||||
|             $tableData = $class::orderBy($orderBy)->get(); | ||||
|             if ($tableData->count()) { | ||||
|                 Cache::forever($name, $tableData); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private function createGateways($company, $user) | ||||
|     { | ||||
|         if (config('ninja.testvars.stripe') && ($this->gateway == 'all' || $this->gateway == 'stripe')) { | ||||
| @ -1016,7 +986,7 @@ class CreateSingleAccount extends Command | ||||
|             $cg->fees_and_limits = $fees_and_limits; | ||||
|             $cg->save(); | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         if (config('ninja.testvars.eway') && ($this->gateway == 'all' || $this->gateway == 'eway')) { | ||||
|             $cg = new CompanyGateway(); | ||||
|             $cg->company_id = $company->id; | ||||
| @ -1038,12 +1008,12 @@ class CreateSingleAccount extends Command | ||||
|             $cg->save(); | ||||
|         } | ||||
| 
 | ||||
|          | ||||
| 
 | ||||
|         if (config('ninja.testvars.gocardless') && ($this->gateway == 'all' || $this->gateway == 'gocardless')) { | ||||
| 
 | ||||
|             $c_settings = ClientSettings::defaults(); | ||||
|             $c_settings->currency_id = '2'; | ||||
|              | ||||
| 
 | ||||
|             $client = Client::factory()->create([ | ||||
|                 'user_id' => $user->id, | ||||
|                 'company_id' => $company->id, | ||||
|  | ||||
| @ -86,8 +86,6 @@ class CreateTestData extends Command | ||||
| 
 | ||||
|         $this->info('Warming up cache'); | ||||
| 
 | ||||
|         $this->warmCache(); | ||||
| 
 | ||||
|         $this->createSmallAccount(); | ||||
|         $this->createMediumAccount(); | ||||
|         $this->createLargeAccount(); | ||||
| @ -673,31 +671,4 @@ class CreateTestData extends Command | ||||
|         return $line_items; | ||||
|     } | ||||
| 
 | ||||
|     private function warmCache() | ||||
|     { | ||||
|         /* Warm up the cache !*/ | ||||
|         $cached_tables = config('ninja.cached_tables'); | ||||
| 
 | ||||
|         foreach ($cached_tables as $name => $class) { | ||||
|             if (! Cache::has($name)) { | ||||
|                 // check that the table exists in case the migration is pending
 | ||||
|                 if (! Schema::hasTable((new $class())->getTable())) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 if ($name == 'payment_terms') { | ||||
|                     $orderBy = 'num_days'; | ||||
|                 } elseif ($name == 'fonts') { | ||||
|                     $orderBy = 'sort_order'; | ||||
|                 } elseif (in_array($name, ['currencies', 'industries', 'languages', 'countries', 'banks'])) { | ||||
|                     $orderBy = 'name'; | ||||
|                 } else { | ||||
|                     $orderBy = 'id'; | ||||
|                 } | ||||
|                 $tableData = $class::orderBy($orderBy)->get(); | ||||
|                 if ($tableData->count()) { | ||||
|                     Cache::forever($name, $tableData); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -84,15 +84,13 @@ class DemoMode extends Command | ||||
| 
 | ||||
|         $this->invoice_repo = new InvoiceRepository(); | ||||
| 
 | ||||
|         $cached_tables = config('ninja.cached_tables'); | ||||
| 
 | ||||
|         $this->info('Migrating'); | ||||
|         Artisan::call('migrate:fresh --force'); | ||||
| 
 | ||||
|         $this->info('Seeding'); | ||||
|         Artisan::call('db:seed --force'); | ||||
| 
 | ||||
|         $this->buildCache(true); | ||||
|         Artisan::call('db:seed --force'); | ||||
|         Artisan::call('cache:clear'); | ||||
| 
 | ||||
|         $this->info('Seeding Random Data'); | ||||
|         $this->createSmallAccount(); | ||||
| @ -623,31 +621,4 @@ class DemoMode extends Command | ||||
|         return $line_items; | ||||
|     } | ||||
| 
 | ||||
|     private function warmCache() | ||||
|     { | ||||
|         /* Warm up the cache !*/ | ||||
|         $cached_tables = config('ninja.cached_tables'); | ||||
| 
 | ||||
|         foreach ($cached_tables as $name => $class) { | ||||
|             if (! Cache::has($name)) { | ||||
|                 // check that the table exists in case the migration is pending
 | ||||
|                 if (! Schema::hasTable((new $class())->getTable())) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 if ($name == 'payment_terms') { | ||||
|                     $orderBy = 'num_days'; | ||||
|                 } elseif ($name == 'fonts') { | ||||
|                     $orderBy = 'sort_order'; | ||||
|                 } elseif (in_array($name, ['currencies', 'industries', 'languages', 'countries', 'banks'])) { | ||||
|                     $orderBy = 'name'; | ||||
|                 } else { | ||||
|                     $orderBy = 'id'; | ||||
|                 } | ||||
|                 $tableData = $class::orderBy($orderBy)->get(); | ||||
|                 if ($tableData->count()) { | ||||
|                     Cache::forever($name, $tableData); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -62,7 +62,6 @@ class HostedMigrations extends Command | ||||
|      */ | ||||
|     public function handle() | ||||
|     { | ||||
|         $this->buildCache(); | ||||
| 
 | ||||
|         if (! MultiDB::userFindAndSetDb($this->option('email'))) { | ||||
|             $this->info('Could not find a user with that email address'); | ||||
|  | ||||
| @ -75,8 +75,6 @@ class ImportMigrations extends Command | ||||
|     { | ||||
|         $this->faker = Factory::create(); | ||||
| 
 | ||||
|         $this->buildCache(); | ||||
| 
 | ||||
|         $path = $this->option('path') ?? public_path('storage/migrations/import'); | ||||
| 
 | ||||
|         $directory = new DirectoryIterator($path); | ||||
|  | ||||
| @ -54,13 +54,6 @@ class PostUpdate extends Command | ||||
| 
 | ||||
|         info('finished migrating'); | ||||
| 
 | ||||
|         $output = []; | ||||
| 
 | ||||
|         // exec('vendor/bin/composer install --no-dev -o', $output);
 | ||||
| 
 | ||||
|         info(print_r($output, 1)); | ||||
|         info('finished running composer install '); | ||||
| 
 | ||||
|         try { | ||||
|             // Artisan::call('optimize');
 | ||||
|             Artisan::call('config:clear'); | ||||
| @ -86,8 +79,7 @@ class PostUpdate extends Command | ||||
| 
 | ||||
|         info('queue restarted'); | ||||
| 
 | ||||
|         $this->buildCache(true); | ||||
| 
 | ||||
|         Artisan::call('cache:clear'); | ||||
|         VersionCheck::dispatch(); | ||||
| 
 | ||||
|         info('Sent for version check'); | ||||
|  | ||||
| @ -48,37 +48,37 @@ class ReactBuilder extends Command | ||||
|     { | ||||
|         if($this->option('type') == 'local') { | ||||
| 
 | ||||
|          | ||||
| 
 | ||||
|         $includes = ''; | ||||
| 
 | ||||
|         $directoryIterator = false; | ||||
|             $includes = ''; | ||||
| 
 | ||||
|         try { | ||||
|             $directoryIterator = new \RecursiveDirectoryIterator(public_path('react/v'.config('ninja.app_version').'/'), \RecursiveDirectoryIterator::SKIP_DOTS); | ||||
|         } catch (\Exception $e) { | ||||
|             $this->error('React files not found'); | ||||
|             return; | ||||
|         } | ||||
|             $directoryIterator = false; | ||||
| 
 | ||||
|         foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) { | ||||
|             if ($file->getExtension() == 'js') { | ||||
|                 if (str_contains($file->getFileName(), 'index-')) { | ||||
|                     $includes .= '<script type="module" crossorigin src="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'"></script>'."\n"; | ||||
|                 } else { | ||||
|                     $includes .= '<link rel="modulepreload" href="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'">'."\n"; | ||||
|             try { | ||||
|                 $directoryIterator = new \RecursiveDirectoryIterator(public_path('react/v'.config('ninja.app_version').'/'), \RecursiveDirectoryIterator::SKIP_DOTS); | ||||
|             } catch (\Exception $e) { | ||||
|                 $this->error('React files not found'); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             foreach (new \RecursiveIteratorIterator($directoryIterator) as $file) { | ||||
|                 if ($file->getExtension() == 'js') { | ||||
|                     if (str_contains($file->getFileName(), 'index-')) { | ||||
|                         $includes .= '<script type="module" crossorigin src="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'"></script>'."\n"; | ||||
|                     } else { | ||||
|                         $includes .= '<link rel="modulepreload" href="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'">'."\n"; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (str_contains($file->getFileName(), '.css')) { | ||||
|                     $includes .= '<link rel="stylesheet" href="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'">'."\n"; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (str_contains($file->getFileName(), '.css')) { | ||||
|                 $includes .= '<link rel="stylesheet" href="/react/v'.config('ninja.app_version').'/'.$file->getFileName().'">'."\n"; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         file_put_contents(resource_path('views/react/head.blade.php'), $includes); | ||||
|             file_put_contents(resource_path('views/react/head.blade.php'), $includes); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|          | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -62,10 +62,10 @@ class SendRemindersCron extends Command | ||||
|     public function handle() | ||||
|     { | ||||
|         Invoice::where('next_send_date', '<=', now()->toDateTimeString()) | ||||
|                  ->whereNull('deleted_at') | ||||
|                  ->where('is_deleted', 0) | ||||
|                  ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) | ||||
|                  ->where('balance', '>', 0) | ||||
|                 ->whereNull('invoices.deleted_at') | ||||
|                 ->where('invoices.is_deleted', 0) | ||||
|                 ->whereIn('invoices.status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) | ||||
|                 ->where('invoices.balance', '>', 0) | ||||
|                  ->whereHas('client', function ($query) { | ||||
|                      $query->where('is_deleted', 0) | ||||
|                            ->where('deleted_at', null); | ||||
| @ -73,6 +73,7 @@ class SendRemindersCron extends Command | ||||
|                  ->whereHas('company', function ($query) { | ||||
|                      $query->where('is_disabled', 0); | ||||
|                  }) | ||||
| 
 | ||||
|                  ->with('invitations')->cursor()->each(function ($invoice) { | ||||
|                      if ($invoice->isPayable()) { | ||||
|                          $reminder_template = $invoice->calculateTemplate('invoice'); | ||||
|  | ||||
| @ -27,6 +27,7 @@ use App\Jobs\Ninja\TaskScheduler; | ||||
| use App\Jobs\Quote\QuoteCheckExpired; | ||||
| use App\Jobs\Subscription\CleanStaleInvoiceOrder; | ||||
| use App\Jobs\Util\DiskCleanup; | ||||
| use App\Jobs\Util\QuoteReminderJob; | ||||
| use App\Jobs\Util\ReminderJob; | ||||
| use App\Jobs\Util\SchedulerCheck; | ||||
| use App\Jobs\Util\UpdateExchangeRates; | ||||
| @ -55,6 +56,9 @@ class Kernel extends ConsoleKernel | ||||
|         /* Send reminders */ | ||||
|         $schedule->job(new ReminderJob())->hourly()->withoutOverlapping()->name('reminder-job')->onOneServer(); | ||||
| 
 | ||||
|         /* Send quote reminders */ | ||||
|         $schedule->job(new QuoteReminderJob())->hourly()->withoutOverlapping()->name('quote-reminder-job')->onOneServer(); | ||||
| 
 | ||||
|         /* Sends recurring invoices*/ | ||||
|         $schedule->job(new RecurringInvoicesCron())->hourly()->withoutOverlapping()->name('recurring-invoice-job')->onOneServer(); | ||||
| 
 | ||||
|  | ||||
| @ -54,8 +54,8 @@ class AccountPlatform extends GenericMixedMetric | ||||
| 
 | ||||
|     public function __construct($string_metric5, $string_metric6, $string_metric7) | ||||
|     { | ||||
|         $this->string_metric5 = $string_metric5; | ||||
|         $this->string_metric6 = $string_metric6; | ||||
|         $this->string_metric5 = mb_convert_encoding($string_metric5, 'UTF-8'); | ||||
|         $this->string_metric6 = mb_convert_encoding($string_metric6, 'UTF-8'); | ||||
|         $this->string_metric7 = $string_metric7; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -55,7 +55,7 @@ class DbQuery extends GenericMixedMetric | ||||
|     public $string_metric8 = 'client_version'; | ||||
| 
 | ||||
|     public $string_metric9 = 'platform'; | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * The counter | ||||
|      * set to 1. | ||||
| @ -66,12 +66,14 @@ class DbQuery extends GenericMixedMetric | ||||
| 
 | ||||
|     public $double_metric2 = 1; | ||||
| 
 | ||||
|     public function __construct($string_metric5, $string_metric6, $int_metric1, $double_metric2, $string_metric7) | ||||
|     public function __construct($string_metric5, $string_metric6, $int_metric1, $double_metric2, $string_metric7, $string_metric8, $string_metric9) | ||||
|     { | ||||
|         $this->int_metric1 = $int_metric1; | ||||
|         $this->string_metric5 = $string_metric5; | ||||
|         $this->string_metric6 = $string_metric6; | ||||
|         $this->double_metric2 = $double_metric2; | ||||
|         $this->string_metric7 = $string_metric7; | ||||
|         $this->string_metric8 = mb_convert_encoding($string_metric8, "UTF-8"); | ||||
|         $this->string_metric9 = mb_convert_encoding($string_metric9, "UTF-8"); | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										61
									
								
								app/DataMapper/Analytics/LoginMeta.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								app/DataMapper/Analytics/LoginMeta.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Invoice Ninja (https://invoiceninja.com). | ||||
|  * | ||||
|  * @link https://github.com/invoiceninja/invoiceninja source repository | ||||
|  * | ||||
|  * @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com) | ||||
|  * | ||||
|  * @license https://www.elastic.co/licensing/elastic-license | ||||
|  */ | ||||
| 
 | ||||
| namespace App\DataMapper\Analytics; | ||||
| 
 | ||||
| use Turbo124\Beacon\ExampleMetric\GenericMixedMetric; | ||||
| 
 | ||||
| class LoginMeta extends GenericMixedMetric | ||||
| { | ||||
|     /** | ||||
|      * The type of Sample. | ||||
|      * | ||||
|      * Monotonically incrementing counter | ||||
|      * | ||||
|      * 	- counter | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     public $type = 'mixed_metric'; | ||||
| 
 | ||||
|     /** | ||||
|      * The name of the counter. | ||||
|      * @var string | ||||
|      */ | ||||
|     public $name = 'login.meta'; | ||||
| 
 | ||||
|     /** | ||||
|      * The datetime of the counter measurement. | ||||
|      * | ||||
|      * date("Y-m-d H:i:s") | ||||
|      * | ||||
|      */ | ||||
|     public $datetime; | ||||
| 
 | ||||
|     /** | ||||
|      * The Class failure name | ||||
|      * set to 0. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     public $string_metric5 = 'email'; | ||||
|     public $string_metric6 = 'ip'; | ||||
|     public $string_metric7 = 'result'; | ||||
| 
 | ||||
|     public $int_metric1 = 1; | ||||
| 
 | ||||
|     public function __construct($string_metric5, $string_metric6, $string_metric7) | ||||
|     { | ||||
|         $this->string_metric7 = $string_metric7; | ||||
|         $this->string_metric6 = $string_metric6; | ||||
|         $this->string_metric5 = $string_metric5; | ||||
|     } | ||||
| } | ||||
| @ -29,7 +29,7 @@ class CompanySettings extends BaseSettings | ||||
| 
 | ||||
|     public $besr_id = ''; //@implemented
 | ||||
| 
 | ||||
|     public $lock_invoices = 'off'; //off,when_sent,when_paid //@implemented
 | ||||
|     public $lock_invoices = 'off'; //off,when_sent,when_paid,end_of_month //@implemented
 | ||||
| 
 | ||||
|     public $enable_client_portal_tasks = false; //@ben to implement
 | ||||
| 
 | ||||
| @ -507,7 +507,25 @@ class CompanySettings extends BaseSettings | ||||
| 
 | ||||
|     public int $task_round_to_nearest = 1; | ||||
| 
 | ||||
|     /** quote reminders */ | ||||
|     public $email_quote_template_reminder1 = ''; | ||||
|     public $email_quote_subject_reminder1 = ''; | ||||
|     public $enable_quote_reminder1 = false; | ||||
|     public $quote_num_days_reminder1 = 0; | ||||
|     public $quote_schedule_reminder1 = ''; //before_valid_until_date,after_valid_until_date,after_quote_date
 | ||||
|     public $quote_late_fee_amount1 = 0; | ||||
|     public $quote_late_fee_percent1 = 0; | ||||
|      | ||||
| 
 | ||||
| 
 | ||||
|     public static $casts = [ | ||||
|         'enable_quote_reminder1'             => 'bool', | ||||
|         'quote_num_days_reminder1'           => 'int', | ||||
|         'quote_schedule_reminder1'           => 'string', | ||||
|         'quote_late_fee_amount1'             => 'float', | ||||
|         'quote_late_fee_percent1'            => 'float', | ||||
|         'email_quote_template_reminder1'     => 'string', | ||||
|         'email_quote_subject_reminder1'      => 'string', | ||||
|         'task_round_up'                      => 'bool', | ||||
|         'task_round_to_nearest'              => 'int', | ||||
|         'e_quote_type'                       => 'string', | ||||
| @ -962,6 +980,7 @@ class CompanySettings extends BaseSettings | ||||
|                 '$invoice.due_date', | ||||
|                 '$invoice.total', | ||||
|                 '$invoice.balance_due', | ||||
|                 '$invoice.project', | ||||
|             ], | ||||
|             'quote_details' => [ | ||||
|                 '$quote.number', | ||||
| @ -969,6 +988,7 @@ class CompanySettings extends BaseSettings | ||||
|                 '$quote.date', | ||||
|                 '$quote.valid_until', | ||||
|                 '$quote.total', | ||||
|                 '$quote.project', | ||||
|             ], | ||||
|             'credit_details' => [ | ||||
|                 '$credit.number', | ||||
|  | ||||
| @ -115,12 +115,32 @@ class EmailTemplateDefaults | ||||
|             case 'email_vendor_notification_body': | ||||
|                 return self::emailVendorNotificationBody(); | ||||
| 
 | ||||
|             case 'email_quote_template_reminder1': | ||||
|                 return self::emailQuoteReminder1Body(); | ||||
| 
 | ||||
|             case 'email_quote_subject_reminder1': | ||||
|                 return self::emailQuoteReminder1Subject(); | ||||
|                  | ||||
|             default: | ||||
|                 return self::emailInvoiceTemplate(); | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static function emailQuoteReminder1Subject() | ||||
|     { | ||||
|         return ctrans('texts.quote_reminder_subject', ['quote' => '$number', 'company' => '$company.name']); | ||||
|     } | ||||
|      | ||||
|     public static function emailQuoteReminder1Body() | ||||
|     { | ||||
| 
 | ||||
|         $invoice_message = '<p>$client<br><br>'.self::transformText('quote_reminder_message').'</p><div class="center">$view_button</div>'; | ||||
| 
 | ||||
|         return $invoice_message; | ||||
| 
 | ||||
|     } | ||||
|      | ||||
|     public static function emailVendorNotificationSubject() | ||||
|     { | ||||
|         return self::transformText('vendor_notification_subject'); | ||||
|  | ||||
| @ -64,9 +64,9 @@ class InvoiceItem | ||||
|     public $task_id = ''; | ||||
| 
 | ||||
|     public $expense_id = ''; | ||||
|      | ||||
| 
 | ||||
|     public $unit_code = 'C62'; | ||||
|      | ||||
| 
 | ||||
|     public static $casts = [ | ||||
|         'task_id' => 'string', | ||||
|         'expense_id' => 'string', | ||||
|  | ||||
| @ -15,7 +15,6 @@ use App\DataMapper\InvoiceItem; | ||||
| 
 | ||||
| class PayPalBalanceAffecting | ||||
| { | ||||
| 
 | ||||
|     private array $key_map = [ | ||||
|         'Date' => 'date', | ||||
|         'Time' => 'time', | ||||
| @ -105,8 +104,10 @@ class PayPalBalanceAffecting | ||||
|     public $discount; | ||||
|     public $creditTransactionalFee; | ||||
|     public $originalInvoiceId; | ||||
|      | ||||
|     public function __construct(private array $import_row){} | ||||
| 
 | ||||
|     public function __construct(private array $import_row) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     public function run(): self | ||||
|     { | ||||
| @ -116,11 +117,11 @@ class PayPalBalanceAffecting | ||||
| 
 | ||||
|             $prop = $this->key_map[$key] ?? false; | ||||
| 
 | ||||
|             if($prop){ | ||||
|             if($prop) { | ||||
| 
 | ||||
|                 echo "Setting {$prop} to {$value}".PHP_EOL; | ||||
|                 $this->{$prop} = $value; | ||||
|                  | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -130,7 +131,7 @@ class PayPalBalanceAffecting | ||||
|     private function cleanUp(): self | ||||
|     { | ||||
| 
 | ||||
|         foreach($this->key_map as $value){ | ||||
|         foreach($this->key_map as $value) { | ||||
|             echo "Setting {$value} to null".PHP_EOL; | ||||
|             $this->{$value} = null; | ||||
|         } | ||||
| @ -154,7 +155,7 @@ class PayPalBalanceAffecting | ||||
| 
 | ||||
|     public function getInvoice(): array | ||||
|     { | ||||
|         $item = new InvoiceItem; | ||||
|         $item = new InvoiceItem(); | ||||
|         $item->cost = $this->gross ?? 0; | ||||
|         $item->product_key = $this->itemId ?? ''; | ||||
|         $item->notes = $this->subject ?? $this->itemDetails; | ||||
| @ -162,7 +163,7 @@ class PayPalBalanceAffecting | ||||
| 
 | ||||
|         return [ | ||||
|             'number' => trim($this->invoiceNumber ?? $this->transactionId), | ||||
|             'date' => str_replace('/','-', $this->date ?? ''), | ||||
|             'date' => str_replace('/', '-', $this->date ?? ''), | ||||
|             'line_items' => [$item], | ||||
|             'name' => $this->name ?? '', | ||||
|             'email' => $this->fromEmailAddress ?? '', | ||||
| @ -174,12 +175,10 @@ class PayPalBalanceAffecting | ||||
|     { | ||||
|         $name_parts = explode(" ", $this->name ?? ''); | ||||
| 
 | ||||
|         if(count($name_parts) == 2) | ||||
|         { | ||||
|         if(count($name_parts) == 2) { | ||||
|             $contact['first_name'] = $name_parts[0]; | ||||
|             $contact['last_name'] = $name_parts[1]; | ||||
|         } | ||||
|         else { | ||||
|         } else { | ||||
|             $contact['first_name'] = $this->name ?? ''; | ||||
|         } | ||||
| 
 | ||||
| @ -188,7 +187,7 @@ class PayPalBalanceAffecting | ||||
| 
 | ||||
|         return $contact; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     private function returnAddress(): array | ||||
|     { | ||||
|         return [ | ||||
| @ -203,13 +202,15 @@ class PayPalBalanceAffecting | ||||
| 
 | ||||
|     private function returnShippingAddress(): array | ||||
|     { | ||||
|         if(strlen($this->shippingAddress ?? '') <3) | ||||
|         if(strlen($this->shippingAddress ?? '') < 3) { | ||||
|             return []; | ||||
|         } | ||||
| 
 | ||||
|         $ship_parts = explode(",", $this->shippingAddress); | ||||
| 
 | ||||
|         if(count($ship_parts) != 7) | ||||
|         if(count($ship_parts) != 7) { | ||||
|             return []; | ||||
|         } | ||||
| 
 | ||||
|         return [ | ||||
|             'shipping_address1' => $ship_parts[2], | ||||
|  | ||||
| @ -220,6 +220,7 @@ class BaseRule implements RuleInterface | ||||
|                 try { | ||||
|                     $this->invoice->saveQuietly(); | ||||
|                 } catch(\Exception $e) { | ||||
|                     nlog("Exception:: BaseRule::" . $e->getMessage()); | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
| @ -261,7 +262,7 @@ class BaseRule implements RuleInterface | ||||
|                 return $this->client->state; | ||||
|             } | ||||
| 
 | ||||
|             return USStates::getState(strlen($this->client->postal_code) > 1 ? $this->client->postal_code : $this->client->shipping_postal_code); | ||||
|             return USStates::getState(strlen($this->client->postal_code ?? '') > 1 ? $this->client->postal_code : $this->client->shipping_postal_code); | ||||
| 
 | ||||
|         } catch (\Exception $e) { | ||||
|             return 'CA'; | ||||
|  | ||||
| @ -207,6 +207,14 @@ class Rule extends BaseRule implements RuleInterface | ||||
|      */ | ||||
|     public function override($item): self | ||||
|     { | ||||
| 
 | ||||
|         $this->tax_rate1 = $item->tax_rate1; | ||||
|         $this->tax_name1 = $item->tax_name1; | ||||
|         $this->tax_rate2 = $item->tax_rate2; | ||||
|         $this->tax_name2 = $item->tax_name2; | ||||
|         $this->tax_rate3 = $item->tax_rate3; | ||||
|         $this->tax_name3 = $item->tax_name3; | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -24,6 +24,7 @@ class TaxData | ||||
| 
 | ||||
|     public function __construct(public Response $origin) | ||||
|     { | ||||
|         // @phpstan-ignore-next-line
 | ||||
|         foreach($origin as $key => $value) { | ||||
|             $this->{$key} = $value; | ||||
|         } | ||||
|  | ||||
| @ -1,24 +0,0 @@ | ||||
| <?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 FACT1. | ||||
|  */ | ||||
| class FACT1 | ||||
| { | ||||
|     public function build() | ||||
|     { | ||||
|         $i = new \InvoiceNinja\EInvoice\Models\FACT1\Invoice(); | ||||
|     } | ||||
| } | ||||
| @ -34006,7 +34006,7 @@ class USStates | ||||
|         'WA', 'WA', 'WA', 'WA', 'WA', 'WA', 'WA', 'AK', 'AK', 'AK', 'AK', 'AK' | ||||
|         ]; | ||||
| 
 | ||||
|         $prefix = substr($zip, 0, 3); | ||||
|         $prefix = substr(($zip ?? ''), 0, 3); | ||||
|         $index = intval($prefix); | ||||
|         /* converts prefix to integer */ | ||||
|         return $zip_by_state[$index] == "--" ? false : $zip_by_state[$index]; | ||||
|  | ||||
							
								
								
									
										28
									
								
								app/Events/Quote/QuoteReminderWasEmailed.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/Events/Quote/QuoteReminderWasEmailed.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Quote Ninja (https://Quoteninja.com). | ||||
|  * | ||||
|  * @link https://github.com/Quoteninja/Quoteninja source repository | ||||
|  * | ||||
|  * @copyright Copyright (c) 2024. Quote Ninja LLC (https://Quoteninja.com) | ||||
|  * | ||||
|  * @license https://www.elastic.co/licensing/elastic-license | ||||
|  */ | ||||
| 
 | ||||
| namespace App\Events\Quote; | ||||
| 
 | ||||
| use App\Models\Company; | ||||
| use App\Models\QuoteInvitation; | ||||
| use Illuminate\Queue\SerializesModels; | ||||
| 
 | ||||
| /** | ||||
|  * Class QuoteReminderWasEmailed. | ||||
|  */ | ||||
| class QuoteReminderWasEmailed | ||||
| { | ||||
|     use SerializesModels; | ||||
| 
 | ||||
|     public function __construct(public QuoteInvitation $invitation, public Company $company, public array $event_vars, public string $template) | ||||
|     { | ||||
|     } | ||||
| } | ||||
							
								
								
									
										44
									
								
								app/Exceptions/DuplicatePaymentException.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								app/Exceptions/DuplicatePaymentException.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Invoice Ninja (https://invoiceninja.com). | ||||
|  * | ||||
|  * @link https://github.com/invoiceninja/invoiceninja source repository | ||||
|  * | ||||
|  * @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com) | ||||
|  * | ||||
|  * @license https://www.elastic.co/licensing/elastic-license | ||||
|  */ | ||||
| 
 | ||||
| namespace App\Exceptions; | ||||
| 
 | ||||
| use Exception; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| class DuplicatePaymentException extends Exception | ||||
| { | ||||
|     /** | ||||
|      * Report the exception. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function report() | ||||
|     { | ||||
|         //
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Render the exception into an HTTP response. | ||||
|      * | ||||
|      * @param  Request  $request | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function render($request) | ||||
|     { | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'message' => 'Duplicate request', | ||||
|         ], 400); | ||||
|          | ||||
|     } | ||||
| } | ||||
| @ -109,10 +109,11 @@ class Handler extends ExceptionHandler | ||||
|             Integration::configureScope(function (Scope $scope): void { | ||||
|                 $name = 'hosted@invoiceninja.com'; | ||||
| 
 | ||||
|                 if (auth()->guard('contact') && auth()->guard('contact')->user()) { | ||||
|                 if (auth()->guard('contact') && auth()->guard('contact')->user()) { // @phpstan-ignore-line
 | ||||
|                     $name = 'Contact = '.auth()->guard('contact')->user()->email; | ||||
|                     $key = auth()->guard('contact')->user()->company->account->key; | ||||
|                 } elseif (auth()->guard('user') && auth()->guard('user')->user()) { | ||||
|                 } elseif (auth()->guard('user') && auth()->guard('user')->user()) { // @phpstan-ignore-line
 | ||||
| 
 | ||||
|                     $name = 'Admin = '.auth()->guard('user')->user()->email; | ||||
|                     $key = auth()->user()->account->key; | ||||
|                 } else { | ||||
| @ -131,13 +132,14 @@ class Handler extends ExceptionHandler | ||||
|             } | ||||
|         } elseif (app()->bound('sentry')) { | ||||
|             Integration::configureScope(function (Scope $scope): void { | ||||
|                 if (auth()->guard('contact') && auth()->guard('contact')->user() && auth()->guard('contact')->user()->company->account->report_errors) { | ||||
|                 if (auth()->guard('contact') && auth()->guard('contact')->user() && auth()->guard('contact')->user()->company->account->report_errors) {// @phpstan-ignore-line
 | ||||
| 
 | ||||
|                     $scope->setUser([ | ||||
|                         'id'    => auth()->guard('contact')->user()->company->account->key, | ||||
|                         'email' => 'anonymous@example.com', | ||||
|                         'name'  => 'Anonymous User', | ||||
|                     ]); | ||||
|                 } elseif (auth()->guard('user') && auth()->guard('user')->user() && auth()->user()->companyIsSet() && auth()->user()->company()->account->report_errors) { | ||||
|                 } elseif (auth()->guard('user') && auth()->guard('user')->user() && auth()->user()->companyIsSet() && auth()->user()->company()->account->report_errors) {// @phpstan-ignore-line
 | ||||
|                     $scope->setUser([ | ||||
|                         'id'    => auth()->user()->account->key, | ||||
|                         'email' => 'anonymous@example.com', | ||||
|  | ||||
| @ -25,8 +25,6 @@ use League\Csv\Writer; | ||||
| 
 | ||||
| class ActivityExport extends BaseExport | ||||
| { | ||||
|     private $entity_transformer; | ||||
| 
 | ||||
|     public string $date_key = 'created_at'; | ||||
| 
 | ||||
|     private string $date_format = 'YYYY-MM-DD'; | ||||
| @ -43,7 +41,7 @@ class ActivityExport extends BaseExport | ||||
|     { | ||||
|         $this->company = $company; | ||||
|         $this->input = $input; | ||||
|         $this->entity_transformer = new ActivityTransformer(); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public function returnJson() | ||||
| @ -111,7 +109,7 @@ class ActivityExport extends BaseExport | ||||
|         $query = Activity::query() | ||||
|                         ->where('company_id', $this->company->id); | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'activities'); | ||||
| 
 | ||||
|         return $query; | ||||
|     } | ||||
| @ -143,10 +141,10 @@ class ActivityExport extends BaseExport | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private function decorateAdvancedFields(Task $task, array $entity): array | ||||
|     { | ||||
|         return $entity; | ||||
|     } | ||||
|     // private function decorateAdvancedFields(Task $task, array $entity): array
 | ||||
|     // {
 | ||||
|     //     return $entity;
 | ||||
|     // }
 | ||||
| 
 | ||||
| 
 | ||||
|     public function processMetaData(array $row, $resource): array | ||||
|  | ||||
| @ -838,12 +838,12 @@ class BaseExport | ||||
|         return ''; | ||||
| 
 | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Apply Product Filters | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      *  | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     public function applyProductFilters(Builder $query): Builder | ||||
| @ -863,13 +863,13 @@ class BaseExport | ||||
| 
 | ||||
|         return $query; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Add Client Filter | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      * @param  mixed $clients | ||||
|      *  | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function addClientFilter(Builder $query, $clients): Builder | ||||
| @ -886,13 +886,13 @@ class BaseExport | ||||
| 
 | ||||
|         return $query; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Add Vendor Filter | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      * @param  string $vendors | ||||
|      *  | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function addVendorFilter(Builder$query, string $vendors): Builder | ||||
| @ -910,13 +910,13 @@ class BaseExport | ||||
| 
 | ||||
|         return $query; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * AddProjectFilter | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      * @param  string $projects | ||||
|      *  | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function addProjectFilter(Builder $query, string $projects): Builder | ||||
| @ -934,13 +934,13 @@ class BaseExport | ||||
| 
 | ||||
|         return $query; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Add Category Filter | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      * @param  string $expense_categories | ||||
|      *  | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function addCategoryFilter(Builder $query, string $expense_categories): Builder | ||||
| @ -959,24 +959,25 @@ class BaseExport | ||||
| 
 | ||||
|         return $query; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Add Payment Status Filters | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      * @param  string $status | ||||
|      *  | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function addPaymentStatusFilters(Builder $query, string $status): Builder | ||||
|     { | ||||
| 
 | ||||
|         /** @var array $status_parameters */ | ||||
|         $status_parameters = explode(',', $status); | ||||
| 
 | ||||
|         if(in_array('all', $status_parameters) || count($status_parameters) == 0) { | ||||
|         if((count($status_parameters) == 0) || in_array('all', $status_parameters)) { | ||||
|             return $query; | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         $query->where(function ($query) use ($status_parameters) { | ||||
|             $payment_filters = []; | ||||
| 
 | ||||
| @ -1016,21 +1017,22 @@ class BaseExport | ||||
|         return $query; | ||||
| 
 | ||||
|     } | ||||
|              | ||||
| 
 | ||||
|     /** | ||||
|      * Add RecurringInvoice Status Filter | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      * @param  string $status | ||||
|      *  | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function addRecurringInvoiceStatusFilter(Builder $query, string $status): Builder | ||||
|     { | ||||
| 
 | ||||
|         /** @var array $status_parameters */ | ||||
|         $status_parameters = explode(',', $status); | ||||
| 
 | ||||
|         if (in_array('all', $status_parameters) || count($status_parameters) == 0){ | ||||
|         if (in_array('all', $status_parameters) || count($status_parameters) == 0) { | ||||
|             return $query; | ||||
|         } | ||||
| 
 | ||||
| @ -1060,7 +1062,7 @@ class BaseExport | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      * @param  string $status | ||||
|      *  | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function addQuoteStatusFilter(Builder $query, string $status): Builder | ||||
| @ -1126,12 +1128,13 @@ class BaseExport | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      * @param  string $status | ||||
|      *  | ||||
|      * | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function addPurchaseOrderStatusFilter(Builder $query, string $status): Builder | ||||
|     { | ||||
|          | ||||
| 
 | ||||
|         /** @var array $status_parameters */ | ||||
|         $status_parameters = explode(',', $status); | ||||
| 
 | ||||
|         if (in_array('all', $status_parameters) || count($status_parameters) == 0) { | ||||
| @ -1179,7 +1182,8 @@ class BaseExport | ||||
|      */ | ||||
|     protected function addInvoiceStatusFilter(Builder $query, string $status): Builder | ||||
|     { | ||||
| 
 | ||||
|                 | ||||
|         /** @var array $status_parameters */ | ||||
|         $status_parameters = explode(',', $status); | ||||
| 
 | ||||
|         if(in_array('all', $status_parameters) || count($status_parameters) == 0) { | ||||
| @ -1234,20 +1238,21 @@ class BaseExport | ||||
| 
 | ||||
|         return $query; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Add Date Range | ||||
|      * | ||||
|      * @param  Builder $query | ||||
|      * @param ?string $table_name | ||||
|      * @return Builder | ||||
|      */ | ||||
|     protected function addDateRange(Builder $query): Builder | ||||
|     protected function addDateRange(Builder $query, ?string $table_name = null): Builder | ||||
|     { | ||||
|         $query = $this->applyProductFilters($query); | ||||
| 
 | ||||
|         $date_range = $this->input['date_range']; | ||||
| 
 | ||||
|         if (array_key_exists('date_key', $this->input) && strlen($this->input['date_key']) > 1) { | ||||
|         if (array_key_exists('date_key', $this->input) && strlen($this->input['date_key']) > 1 && ($table_name && $this->columnExists($table_name, $this->input['date_key']))) { | ||||
|             $this->date_key = $this->input['date_key']; | ||||
|         } | ||||
| 
 | ||||
| @ -1578,7 +1583,7 @@ class BaseExport | ||||
| 
 | ||||
|     public function queueDocuments(Builder $query) | ||||
|     { | ||||
|          | ||||
| 
 | ||||
|         if($query->getModel() instanceof Document) { | ||||
|             $documents = $query->pluck('id')->toArray(); | ||||
|         } else { | ||||
| @ -1604,5 +1609,18 @@ class BaseExport | ||||
|             ZipDocuments::dispatch($documents, $this->company, $user); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|      | ||||
|     /** | ||||
|      * Tests that the column exists | ||||
|      * on the table prior to adding it to  | ||||
|      * the query builder | ||||
|      * | ||||
|      * @param  string $table | ||||
|      * @param  string $column | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function columnExists($table, $column): bool | ||||
|     { | ||||
|         return \Illuminate\Support\Facades\Schema::hasColumn($table, $column); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -127,10 +127,11 @@ class ClientExport extends BaseExport | ||||
|                                 ->withTrashed() | ||||
|                                 ->where('company_id', $this->company->id); | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) | ||||
|         if(!$this->input['include_deleted'] ?? false) { | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query,' clients'); | ||||
| 
 | ||||
|         if($this->input['document_email_attachment'] ?? false) { | ||||
|             $this->queueDocuments($query); | ||||
| @ -242,16 +243,16 @@ class ClientExport extends BaseExport | ||||
|         return $entity; | ||||
|     } | ||||
| 
 | ||||
|     private function calculateStatus($client) | ||||
|     { | ||||
|         if ($client->is_deleted) { | ||||
|             return ctrans('texts.deleted'); | ||||
|         } | ||||
|     // private function calculateStatus($client)
 | ||||
|     // {
 | ||||
|     //     if ($client->is_deleted) {
 | ||||
|     //         return ctrans('texts.deleted');
 | ||||
|     //     }
 | ||||
| 
 | ||||
|         if ($client->deleted_at) { | ||||
|             return ctrans('texts.archived'); | ||||
|         } | ||||
|     //     if ($client->deleted_at) {
 | ||||
|     //         return ctrans('texts.archived');
 | ||||
|     //     }
 | ||||
| 
 | ||||
|         return ctrans('texts.active'); | ||||
|     } | ||||
|     //     return ctrans('texts.active');
 | ||||
|     // }
 | ||||
| } | ||||
|  | ||||
| @ -59,11 +59,11 @@ class ContactExport extends BaseExport | ||||
| 
 | ||||
|         $query = ClientContact::query() | ||||
|                         ->where('company_id', $this->company->id) | ||||
|                         ->whereHas('client', function ($q){ | ||||
|                         ->whereHas('client', function ($q) { | ||||
|                             $q->where('is_deleted', false); | ||||
|                         }); | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'client_contacts'); | ||||
| 
 | ||||
|         return $query; | ||||
| 
 | ||||
| @ -155,7 +155,7 @@ class ContactExport extends BaseExport | ||||
|         } | ||||
| 
 | ||||
|         if (in_array('client.user_id', $this->input['report_keys'])) { | ||||
|             $entity['client.user_id'] = $client->user ? $client->user->present()->name() : ''; | ||||
|             $entity['client.user_id'] = $client->user ? $client->user->present()->name() : '';// @phpstan-ignore-line
 | ||||
|         } | ||||
| 
 | ||||
|         if (in_array('client.assigned_user_id', $this->input['report_keys'])) { | ||||
|  | ||||
| @ -102,13 +102,13 @@ class CreditExport extends BaseExport | ||||
|         $query = Credit::query() | ||||
|                         ->withTrashed() | ||||
|                         ->with('client') | ||||
|                         ->whereHas('client', function ($q){ | ||||
|                         ->whereHas('client', function ($q) { | ||||
|                             $q->where('is_deleted', false); | ||||
|                         }) | ||||
|                         ->where('company_id', $this->company->id) | ||||
|                         ->where('is_deleted', $this->input['include_deleted'] ?? false); | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'credits'); | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
| @ -241,7 +241,7 @@ class CreditExport extends BaseExport | ||||
|         } | ||||
| 
 | ||||
|         if (in_array('credit.user_id', $this->input['report_keys'])) { | ||||
|             $entity['credit.user_id'] = $credit->user ? $credit->user->present()->name() : ''; | ||||
|             $entity['credit.user_id'] = $credit->user ? $credit->user->present()->name() : ''; //@phpstan-ignore-line
 | ||||
|         } | ||||
| 
 | ||||
|         return $entity; | ||||
|  | ||||
| @ -76,7 +76,7 @@ class DocumentExport extends BaseExport | ||||
| 
 | ||||
|         $query = Document::query()->where('company_id', $this->company->id); | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'documents'); | ||||
| 
 | ||||
|         if($this->input['document_email_attachment'] ?? false) { | ||||
|             $this->queueDocuments($query); | ||||
|  | ||||
| @ -83,13 +83,13 @@ class ExpenseExport extends BaseExport | ||||
|                         ->with('client') | ||||
|                         ->withTrashed() | ||||
|                         ->where('company_id', $this->company->id); | ||||
|          | ||||
|                          | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) { // @phpstan-ignore-line
 | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'expenses'); | ||||
| 
 | ||||
|         if($this->input['status'] ?? false) { | ||||
|             $query = $this->addExpenseStatusFilter($query, $this->input['status']); | ||||
| @ -220,17 +220,17 @@ class ExpenseExport extends BaseExport | ||||
|         //     $entity['expense.client'] = $expense->client ? $expense->client->present()->name() : '';
 | ||||
|         // }
 | ||||
| 
 | ||||
|         // if (in_array('expense.invoice_id', $this->input['report_keys'])) {
 | ||||
|         //     $entity['expense.invoice_id'] = $expense->invoice ? $expense->invoice->number : '';
 | ||||
|         // }
 | ||||
|         if (in_array('expense.invoice_id', $this->input['report_keys'])) { | ||||
|             $entity['expense.invoice_id'] = $expense->invoice ? $expense->invoice->number : ''; | ||||
|         } | ||||
| 
 | ||||
|         // if (in_array('expense.category', $this->input['report_keys'])) {
 | ||||
|         //     $entity['expense.category'] = $expense->category ? $expense->category->name : '';
 | ||||
|         // }
 | ||||
| 
 | ||||
|         // if (in_array('expense.vendor_id', $this->input['report_keys'])) {
 | ||||
|         //     $entity['expense.vendor'] = $expense->vendor ? $expense->vendor->name : '';
 | ||||
|         // }
 | ||||
|         if (in_array('expense.vendor_id', $this->input['report_keys'])) { | ||||
|             $entity['expense.vendor'] = $expense->vendor ? $expense->vendor->name : ''; | ||||
|         } | ||||
| 
 | ||||
|         // if (in_array('expense.payment_type_id', $this->input['report_keys'])) {
 | ||||
|         //     $entity['expense.payment_type_id'] = $expense->payment_type ? $expense->payment_type->name : '';
 | ||||
| @ -259,10 +259,17 @@ class ExpenseExport extends BaseExport | ||||
|     { | ||||
|         $precision = $expense->currency->precision ?? 2; | ||||
| 
 | ||||
|         $entity['expense.net_amount'] = round($expense->amount, $precision); | ||||
| 
 | ||||
|         if($expense->calculate_tax_by_amount) { | ||||
| 
 | ||||
|             $total_tax_amount = round($expense->tax_amount1 + $expense->tax_amount2 + $expense->tax_amount3, $precision); | ||||
|              | ||||
|             if($expense->uses_inclusive_taxes) { | ||||
|                 $entity['expense.net_amount'] = round($expense->amount, $precision) - $total_tax_amount; | ||||
|             } | ||||
|             else { | ||||
|                 $entity['expense.net_amount'] = round($expense->amount, $precision); | ||||
|             } | ||||
| 
 | ||||
|         } else { | ||||
| 
 | ||||
|             if($expense->uses_inclusive_taxes) { | ||||
|  | ||||
| @ -57,17 +57,17 @@ class InvoiceExport extends BaseExport | ||||
|         $query = Invoice::query() | ||||
|                         ->withTrashed() | ||||
|                         ->with('client') | ||||
|                         ->whereHas('client', function ($q){ | ||||
|                         ->whereHas('client', function ($q) { | ||||
|                             $q->where('is_deleted', false); | ||||
|                         }) | ||||
|                         ->where('company_id', $this->company->id); | ||||
|          | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) {// @phpstan-ignore-line
 | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'invoices'); | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
| @ -166,7 +166,8 @@ class InvoiceExport extends BaseExport | ||||
|         } | ||||
| 
 | ||||
|         if (in_array('invoice.user_id', $this->input['report_keys'])) { | ||||
|             $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : ''; | ||||
|             $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : ''; // @phpstan-ignore-line
 | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         return $entity; | ||||
|  | ||||
| @ -70,16 +70,16 @@ class InvoiceItemExport extends BaseExport | ||||
|         $query = Invoice::query() | ||||
|                         ->withTrashed() | ||||
|                         ->with('client') | ||||
|                         ->whereHas('client', function ($q){ | ||||
|                         ->whereHas('client', function ($q) { | ||||
|                             $q->where('is_deleted', false); | ||||
|                         }) | ||||
|                         ->where('company_id', $this->company->id); | ||||
|                          | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) {// @phpstan-ignore-line
 | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'invoices'); | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
| @ -258,7 +258,7 @@ class InvoiceItemExport extends BaseExport | ||||
|         } | ||||
| 
 | ||||
|         if (in_array('invoice.user_id', $this->input['report_keys'])) { | ||||
|             $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : ''; | ||||
|             $entity['invoice.user_id'] = $invoice->user ? $invoice->user->present()->name() : '';// @phpstan-ignore-line
 | ||||
|         } | ||||
| 
 | ||||
|         return $entity; | ||||
|  | ||||
| @ -56,13 +56,13 @@ class PaymentExport extends BaseExport | ||||
| 
 | ||||
|         $query = Payment::query() | ||||
|                             ->withTrashed() | ||||
|                             ->whereHas('client', function ($q){ | ||||
|                             ->whereHas('client', function ($q) { | ||||
|                                 $q->where('is_deleted', false); | ||||
|                             }) | ||||
|                             ->where('company_id', $this->company->id) | ||||
|                             ->where('is_deleted', 0); | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'payments'); | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
| @ -71,7 +71,7 @@ class PaymentExport extends BaseExport | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addPaymentStatusFilters($query, $this->input['status'] ?? ''); | ||||
|          | ||||
| 
 | ||||
|         if($this->input['document_email_attachment'] ?? false) { | ||||
|             $this->queueDocuments($query); | ||||
|         } | ||||
|  | ||||
| @ -74,13 +74,12 @@ class ProductExport extends BaseExport | ||||
|         $query = Product::query() | ||||
|                         ->withTrashed() | ||||
|                         ->where('company_id', $this->company->id); | ||||
|                          | ||||
|                          | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) { //@phpstan-ignore-line
 | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'products'); | ||||
| 
 | ||||
|         if($this->input['document_email_attachment'] ?? false) { | ||||
|             $this->queueDocuments($query); | ||||
| @ -133,16 +132,16 @@ class ProductExport extends BaseExport | ||||
|         // return $this->decorateAdvancedFields($product, $entity);
 | ||||
|     } | ||||
| 
 | ||||
|     private function decorateAdvancedFields(Product $product, array $entity): array | ||||
|     { | ||||
|         if (in_array('vendor_id', $this->input['report_keys'])) { | ||||
|             $entity['vendor'] = $product->vendor()->exists() ? $product->vendor->name : ''; | ||||
|         } | ||||
|     // private function decorateAdvancedFields(Product $product, array $entity): array
 | ||||
|     // {
 | ||||
|     //     if (in_array('vendor_id', $this->input['report_keys'])) {
 | ||||
|     //         $entity['vendor'] = $product->vendor()->exists() ? $product->vendor->name : '';
 | ||||
|     //     }
 | ||||
| 
 | ||||
|         // if (array_key_exists('project_id', $this->input['report_keys'])) {
 | ||||
|         //     $entity['project'] = $product->project()->exists() ? $product->project->name : '';
 | ||||
|         // }
 | ||||
|     //     // if (array_key_exists('project_id', $this->input['report_keys'])) {
 | ||||
|     //     //     $entity['project'] = $product->project()->exists() ? $product->project->name : '';
 | ||||
|     //     // }
 | ||||
| 
 | ||||
|         return $entity; | ||||
|     } | ||||
|     //     return $entity;
 | ||||
|     // }
 | ||||
| } | ||||
|  | ||||
| @ -25,6 +25,7 @@ class ProductSalesExport extends BaseExport | ||||
| { | ||||
|     public string $date_key = 'created_at'; | ||||
| 
 | ||||
|     /** @var Collection<\App\Models\Product> $products*/ | ||||
|     protected Collection $products; | ||||
| 
 | ||||
|     public Writer $csv; | ||||
| @ -65,11 +66,11 @@ class ProductSalesExport extends BaseExport | ||||
|         'custom_value4' => 'custom_value4', | ||||
|     ]; | ||||
| 
 | ||||
|     private array $decorate_keys = [ | ||||
|         'client', | ||||
|         'currency', | ||||
|         'date', | ||||
|     ]; | ||||
|     // private array $decorate_keys = [
 | ||||
|     //     'client',
 | ||||
|     //     'currency',
 | ||||
|     //     'date',
 | ||||
|     // ];
 | ||||
| 
 | ||||
|     public function __construct(Company $company, array $input) | ||||
|     { | ||||
| @ -80,20 +81,20 @@ class ProductSalesExport extends BaseExport | ||||
| 
 | ||||
|     public function filterByProducts($query) | ||||
|     { | ||||
|      | ||||
| 
 | ||||
|         $product_keys = &$this->input['product_key']; | ||||
| 
 | ||||
|         if ($product_keys && !empty($this->input['product_key'])) { | ||||
| 
 | ||||
|             $keys = explode(",", $product_keys); | ||||
|             $query->where(function ($q) use ($keys){ | ||||
|             $query->where(function ($q) use ($keys) { | ||||
| 
 | ||||
|                 foreach($keys as $key)  {     | ||||
|                 foreach($keys as $key) { | ||||
|                     $q->orWhereJsonContains('line_items', ['product_key' => $key]); | ||||
|                 } | ||||
| 
 | ||||
|             }); | ||||
|              | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         return $query; | ||||
| @ -121,14 +122,14 @@ class ProductSalesExport extends BaseExport | ||||
|         //insert the header
 | ||||
|         $query = Invoice::query() | ||||
|                         ->withTrashed() | ||||
|                         ->whereHas('client', function ($q){ | ||||
|                         ->whereHas('client', function ($q) { | ||||
|                             $q->where('is_deleted', false); | ||||
|                         }) | ||||
|                         ->where('company_id', $this->company->id) | ||||
|                         ->where('is_deleted', 0) | ||||
|                         ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL, Invoice::STATUS_PAID]); | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'invoices'); | ||||
| 
 | ||||
|         $query = $this->filterByClients($query); | ||||
| 
 | ||||
| @ -138,30 +139,29 @@ class ProductSalesExport extends BaseExport | ||||
| 
 | ||||
|         $product_keys = &$this->input['product_key']; | ||||
| 
 | ||||
|         if($product_keys){ | ||||
|         if($product_keys) { | ||||
|             $product_keys = explode(",", $product_keys); | ||||
|         } | ||||
| 
 | ||||
|         $query->cursor() | ||||
|               ->each(function ($invoice) use($product_keys) { | ||||
|               ->each(function ($invoice) use ($product_keys) { | ||||
|                   foreach ($invoice->line_items as $item) { | ||||
| 
 | ||||
|                     if($product_keys) | ||||
|                     { | ||||
|                      if(in_array($item->product_key, $product_keys)) | ||||
|                         $this->csv->insertOne($this->buildRow($invoice, $item)); | ||||
|                     } | ||||
|                     else { | ||||
|                         $this->csv->insertOne($this->buildRow($invoice, $item)); | ||||
|                     } | ||||
|                      | ||||
|                       if($product_keys) { | ||||
|                           if(in_array($item->product_key, $product_keys)) { | ||||
|                               $this->csv->insertOne($this->buildRow($invoice, $item)); | ||||
|                           } | ||||
|                       } else { | ||||
|                           $this->csv->insertOne($this->buildRow($invoice, $item)); | ||||
|                       } | ||||
| 
 | ||||
|                   } | ||||
|               }); | ||||
| 
 | ||||
| 
 | ||||
|         $grouped = $this->sales->groupBy('product_key')->map(function ($key, $value) use($product_keys){ | ||||
|         $grouped = $this->sales->groupBy('product_key')->map(function ($key, $value) use ($product_keys) { | ||||
| 
 | ||||
|             if($product_keys && !in_array($value, $product_keys)){ | ||||
|             if($product_keys && !in_array($value, $product_keys)) { | ||||
|                 return false; | ||||
|             } | ||||
| 
 | ||||
| @ -185,7 +185,8 @@ class ProductSalesExport extends BaseExport | ||||
| 
 | ||||
|         })->reject(function ($value) { | ||||
|             return $value === false; | ||||
|         });; | ||||
|         }); | ||||
|         ; | ||||
| 
 | ||||
|         $this->csv->insertOne([]); | ||||
|         $this->csv->insertOne([]); | ||||
| @ -327,10 +328,10 @@ class ProductSalesExport extends BaseExport | ||||
|      * getProduct | ||||
|      * | ||||
|      * @param  string $product_key | ||||
|      * @return Product | ||||
|      * @return ?\Illuminate\Database\Eloquent\Model | ||||
|      */ | ||||
|     private function getProduct(string $product_key): ?Product | ||||
|     { | ||||
|         return $this->products->firstWhere('product_key', $product_key); | ||||
|     } | ||||
|     // private function getProduct(string $product_key)
 | ||||
|     // {
 | ||||
|     //     return $this->products->firstWhere('product_key', $product_key);
 | ||||
|     // }
 | ||||
| } | ||||
|  | ||||
| @ -58,22 +58,23 @@ class PurchaseOrderExport extends BaseExport | ||||
|         $query = PurchaseOrder::query() | ||||
|                         ->withTrashed() | ||||
|                         ->with('vendor') | ||||
|                         ->whereHas('vendor', function ($q){ | ||||
|                         ->whereHas('vendor', function ($q) { | ||||
|                             $q->where('is_deleted', false); | ||||
|                         }) | ||||
|                         ->where('company_id', $this->company->id); | ||||
|                          | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) { // @phpstan-ignore-line
 | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'purchase_orders'); | ||||
| 
 | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
|         if($clients) | ||||
|         if($clients) { | ||||
|             $query = $this->addClientFilter($query, $clients); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addPurchaseOrderStatusFilter($query, $this->input['status'] ?? ''); | ||||
| 
 | ||||
| @ -166,7 +167,8 @@ class PurchaseOrderExport extends BaseExport | ||||
|         } | ||||
| 
 | ||||
|         if (in_array('purchase_order.user_id', $this->input['report_keys'])) { | ||||
|             $entity['purchase_order.user_id'] = $purchase_order->user ? $purchase_order->user->present()->name() : ''; | ||||
|             $entity['purchase_order.user_id'] = $purchase_order->user ? $purchase_order->user->present()->name() : ''; // @phpstan-ignore-line
 | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         if (in_array('purchase_order.assigned_user_id', $this->input['report_keys'])) { | ||||
|  | ||||
| @ -62,16 +62,16 @@ class PurchaseOrderItemExport extends BaseExport | ||||
| 
 | ||||
|         $query = PurchaseOrder::query() | ||||
|                         ->withTrashed() | ||||
|                         ->whereHas('vendor', function ($q){ | ||||
|                         ->whereHas('vendor', function ($q) { | ||||
|                             $q->where('is_deleted', false); | ||||
|                         }) | ||||
|                         ->with('vendor')->where('company_id', $this->company->id); | ||||
|                          | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) { | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'purchase_orders'); | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
|  | ||||
| @ -31,11 +31,11 @@ class QuoteExport extends BaseExport | ||||
| 
 | ||||
|     private Decorator $decorator; | ||||
| 
 | ||||
|     private array $decorate_keys = [ | ||||
|         'client', | ||||
|         'currency', | ||||
|         'invoice', | ||||
|     ]; | ||||
|     // private array $decorate_keys = [
 | ||||
|     //     'client',
 | ||||
|     //     'currency',
 | ||||
|     //     'invoice',
 | ||||
|     // ];
 | ||||
| 
 | ||||
|     public function __construct(Company $company, array $input) | ||||
|     { | ||||
| @ -64,16 +64,16 @@ class QuoteExport extends BaseExport | ||||
|         $query = Quote::query() | ||||
|                         ->withTrashed() | ||||
|                         ->with('client') | ||||
|                         ->whereHas('client', function ($q){ | ||||
|                         ->whereHas('client', function ($q) { | ||||
|                             $q->where('is_deleted', false); | ||||
|                         }) | ||||
|                         ->where('company_id', $this->company->id); | ||||
|                          | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) { | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'quotes'); | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
|  | ||||
| @ -65,16 +65,16 @@ class QuoteItemExport extends BaseExport | ||||
| 
 | ||||
|         $query = Quote::query() | ||||
|                             ->withTrashed() | ||||
|                             ->whereHas('client', function ($q){ | ||||
|                             ->whereHas('client', function ($q) { | ||||
|                                 $q->where('is_deleted', false); | ||||
|                             }) | ||||
|                             ->with('client')->where('company_id', $this->company->id); | ||||
|                              | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) { | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'quotes'); | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
|  | ||||
| @ -56,16 +56,16 @@ class RecurringInvoiceExport extends BaseExport | ||||
|         $query = RecurringInvoice::query() | ||||
|                         ->withTrashed() | ||||
|                         ->with('client') | ||||
|                         ->whereHas('client', function ($q){ | ||||
|                         ->whereHas('client', function ($q) { | ||||
|                             $q->where('is_deleted', false); | ||||
|                         }) | ||||
|                         ->where('company_id', $this->company->id); | ||||
|                          | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) { | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'recurring_invoices'); | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
|  | ||||
| @ -31,7 +31,7 @@ class TaskExport extends BaseExport | ||||
| 
 | ||||
|     public string $date_key = 'created_at'; | ||||
| 
 | ||||
|     private string $date_format = 'YYYY-MM-DD'; | ||||
|     private string $date_format = 'Y-m-d'; | ||||
| 
 | ||||
|     public Writer $csv; | ||||
| 
 | ||||
| @ -69,22 +69,24 @@ class TaskExport extends BaseExport | ||||
|         $query = Task::query() | ||||
|                         ->withTrashed() | ||||
|                         ->where('company_id', $this->company->id); | ||||
|                          | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) { | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|          | ||||
|         $query = $this->addDateRange($query, 'tasks'); | ||||
| 
 | ||||
|         $clients = &$this->input['client_id']; | ||||
| 
 | ||||
|         if($clients) | ||||
|         if($clients) { | ||||
|             $query = $this->addClientFilter($query, $clients); | ||||
|         } | ||||
| 
 | ||||
|         $document_attachments = &$this->input['document_email_attachment']; | ||||
| 
 | ||||
|         if($document_attachments)  | ||||
|         if($document_attachments) { | ||||
|             $this->queueDocuments($query); | ||||
|         } | ||||
| 
 | ||||
|         return $query; | ||||
| 
 | ||||
| @ -178,23 +180,17 @@ class TaskExport extends BaseExport | ||||
| 
 | ||||
|         $logs = json_decode($task->time_log, 1); | ||||
| 
 | ||||
|         $date_format_default = 'Y-m-d'; | ||||
| 
 | ||||
|         $date_format = DateFormat::find($task->company->settings->date_format_id); | ||||
| 
 | ||||
|         if ($date_format) { | ||||
|             $date_format_default = $date_format->format; | ||||
|         } | ||||
|         $date_format_default = $this->date_format; | ||||
| 
 | ||||
|         foreach ($logs as $key => $item) { | ||||
|             if (in_array('task.start_date', $this->input['report_keys']) || in_array('start_date', $this->input['report_keys'])) { | ||||
|                 $carbon_object = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name); | ||||
|                 $carbon_object = Carbon::createFromTimeStamp((int)$item[0])->setTimezone($timezone_name); | ||||
|                 $entity['task.start_date'] = $carbon_object->format($date_format_default); | ||||
|                 $entity['task.start_time'] = $carbon_object->format('H:i:s'); | ||||
|             } | ||||
| 
 | ||||
|             if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] > 0) { | ||||
|                 $carbon_object = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name); | ||||
|                 $carbon_object = Carbon::createFromTimeStamp((int)$item[1])->setTimezone($timezone_name); | ||||
|                 $entity['task.end_date'] = $carbon_object->format($date_format_default); | ||||
|                 $entity['task.end_time'] = $carbon_object->format('H:i:s'); | ||||
|             } | ||||
| @ -224,7 +220,7 @@ class TaskExport extends BaseExport | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Add Task Status Filter | ||||
|      * | ||||
| @ -234,7 +230,7 @@ class TaskExport extends BaseExport | ||||
|      */ | ||||
|     protected function addTaskStatusFilter(Builder $query, string $status): Builder | ||||
|     { | ||||
|      | ||||
|         /** @var array $status_parameters */ | ||||
|         $status_parameters = explode(',', $status); | ||||
| 
 | ||||
|         if (in_array('all', $status_parameters) || count($status_parameters) == 0) { | ||||
|  | ||||
| @ -63,12 +63,12 @@ class VendorExport extends BaseExport | ||||
|         $query = Vendor::query()->with('contacts') | ||||
|                         ->withTrashed() | ||||
|                         ->where('company_id', $this->company->id); | ||||
|                          | ||||
|         if(!$this->input['include_deleted'] ?? false){ | ||||
| 
 | ||||
|         if(!$this->input['include_deleted'] ?? false) { | ||||
|             $query->where('is_deleted', 0); | ||||
|         } | ||||
| 
 | ||||
|         $query = $this->addDateRange($query); | ||||
|         $query = $this->addDateRange($query, 'vendors'); | ||||
| 
 | ||||
|         if($this->input['document_email_attachment'] ?? false) { | ||||
|             $this->queueDocuments($query); | ||||
| @ -171,16 +171,16 @@ class VendorExport extends BaseExport | ||||
|         return $entity; | ||||
|     } | ||||
| 
 | ||||
|     private function calculateStatus($vendor) | ||||
|     { | ||||
|         if ($vendor->is_deleted) { | ||||
|             return ctrans('texts.deleted'); | ||||
|         } | ||||
|     // private function calculateStatus($vendor)
 | ||||
|     // {
 | ||||
|     //     if ($vendor->is_deleted) {
 | ||||
|     //         return ctrans('texts.deleted');
 | ||||
|     //     }
 | ||||
| 
 | ||||
|         if ($vendor->deleted_at) { | ||||
|             return ctrans('texts.archived'); | ||||
|         } | ||||
|     //     if ($vendor->deleted_at) {
 | ||||
|     //         return ctrans('texts.archived');
 | ||||
|     //     }
 | ||||
| 
 | ||||
|         return ctrans('texts.active'); | ||||
|     } | ||||
|     //     return ctrans('texts.active');
 | ||||
|     // }
 | ||||
| } | ||||
|  | ||||
| @ -25,7 +25,7 @@ class ContactDecorator implements DecoratorInterface | ||||
|             $contact = $entity->contacts()->first(); | ||||
|         } elseif($entity->client) { | ||||
|             $contact = $entity->client->primary_contact->first() ?? $entity->client->contacts()->whereNotNull('email')->first(); | ||||
|         } elseif($entity->vendor) {  | ||||
|         } elseif($entity->vendor) { | ||||
|             $contact = $entity->vendor->primary_contact->first() ?? $entity->vendor->contacts()->whereNotNull('email')->first(); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -60,7 +60,7 @@ class TaskDecorator extends Decorator implements DecoratorInterface | ||||
| 
 | ||||
|         if(is_array($logs)) { | ||||
|             $item = $logs[0]; | ||||
|             return Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name)->format($date_format_default); | ||||
|             return Carbon::createFromTimeStamp((int)$item[0])->setTimezone($timezone_name)->format($date_format_default); | ||||
|         } | ||||
| 
 | ||||
|         return ''; | ||||
| @ -89,7 +89,7 @@ class TaskDecorator extends Decorator implements DecoratorInterface | ||||
| 
 | ||||
|         if(is_array($logs)) { | ||||
|             $item = $logs[1]; | ||||
|             return Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name)->format($date_format_default); | ||||
|             return Carbon::createFromTimeStamp((int)$item[1])->setTimezone($timezone_name)->format($date_format_default); | ||||
|         } | ||||
| 
 | ||||
|         return ''; | ||||
|  | ||||
| @ -23,14 +23,13 @@ class BankIntegrationFactory | ||||
|         $bank_integration->company_id = $company_id; | ||||
| 
 | ||||
|         $bank_integration->provider_name = ''; | ||||
|         $bank_integration->bank_account_id = ''; | ||||
|         $bank_integration->bank_account_name = ''; | ||||
|         $bank_integration->bank_account_number = ''; | ||||
|         $bank_integration->bank_account_status = ''; | ||||
|         $bank_integration->bank_account_type = ''; | ||||
|         $bank_integration->balance = 0; | ||||
|         $bank_integration->currency = ''; | ||||
|         $bank_integration->auto_sync = 1; | ||||
|         $bank_integration->auto_sync = true; | ||||
| 
 | ||||
|         return $bank_integration; | ||||
|     } | ||||
|  | ||||
| @ -29,7 +29,7 @@ class ClientFactory | ||||
|         $client->balance = 0; | ||||
|         $client->paid_to_date = 0; | ||||
|         $client->country_id = null; | ||||
|         $client->is_deleted = 0; | ||||
|         $client->is_deleted = false; | ||||
|         $client->client_hash = Str::random(40); | ||||
|         $client->settings = ClientSettings::defaults(); | ||||
|         $client->classification = ''; | ||||
|  | ||||
| @ -33,7 +33,7 @@ class CloneQuoteToProjectFactory | ||||
|         $project->custom_value2 = ''; | ||||
|         $project->custom_value3 = ''; | ||||
|         $project->custom_value4 = ''; | ||||
|         $project->is_deleted = 0; | ||||
|         $project->is_deleted = false; | ||||
| 
 | ||||
|         return $project; | ||||
|     } | ||||
|  | ||||
| @ -48,7 +48,7 @@ class CompanyFactory | ||||
|         $company->markdown_email_enabled = true; | ||||
|         $company->markdown_enabled = false; | ||||
|         $company->tax_data = new TaxModel(); | ||||
|         $company->first_month_of_year = 1; | ||||
|         $company->first_month_of_year = '1'; | ||||
|         $company->smtp_encryption = 'tls'; | ||||
|         $company->smtp_host = ''; | ||||
|         $company->smtp_local_domain = ''; | ||||
| @ -56,7 +56,7 @@ class CompanyFactory | ||||
|         $company->smtp_port = ''; | ||||
|         $company->smtp_username = ''; | ||||
|         $company->smtp_verify_peer = true; | ||||
|          | ||||
| 
 | ||||
|         return $company; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -24,7 +24,7 @@ class CompanyGatewayFactory | ||||
|         $company_gateway->require_shipping_address = false; | ||||
|         $company_gateway->config = encrypt(json_encode(new \stdClass())); | ||||
|         $company_gateway->always_show_required_fields = true; | ||||
|          | ||||
| 
 | ||||
|         return $company_gateway; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -52,7 +52,7 @@ class PurchaseOrderFactory | ||||
|         $purchase_order->exchange_rate = 1; | ||||
|         $purchase_order->total_taxes = 0; | ||||
|         $purchase_order->uses_inclusive_taxes = false; | ||||
|          | ||||
| 
 | ||||
|         return $purchase_order; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -82,11 +82,15 @@ class RecurringExpenseToExpenseFactory | ||||
|         } else { | ||||
|             $locale = $recurring_expense->company->locale(); | ||||
| 
 | ||||
|             $date_formats = Cache::get('date_formats'); | ||||
|             //@deprecated
 | ||||
|             // $date_formats = Cache::get('date_formats');
 | ||||
| 
 | ||||
|             $date_format = $date_formats->filter(function ($item) use ($recurring_expense) { | ||||
|             /** @var \Illuminate\Support\Collection<\App\Models\DateFormat> */ | ||||
|             $date_formats = app('date_formats'); | ||||
| 
 | ||||
|             $date_format = $date_formats->first(function ($item) use ($recurring_expense) { | ||||
|                 return $item->id == $recurring_expense->company->settings->date_format_id; | ||||
|             })->first()->format; | ||||
|             })->format; | ||||
|         } | ||||
| 
 | ||||
|         Carbon::setLocale($locale); | ||||
| @ -144,7 +148,7 @@ class RecurringExpenseToExpenseFactory | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             if (Str::contains($match, '|')) { | ||||
|             // if (Str::contains($match, '|')) {
 | ||||
|                 $parts = explode('|', $match); // [ '[MONTH', 'MONTH+2]' ]
 | ||||
| 
 | ||||
|                 $left = substr($parts[0], 1); // 'MONTH'
 | ||||
| @ -182,7 +186,7 @@ class RecurringExpenseToExpenseFactory | ||||
|                     $value, | ||||
|                     1 | ||||
|                 ); | ||||
|             } | ||||
|             // }
 | ||||
|         } | ||||
| 
 | ||||
|         // Second case with more common calculations.
 | ||||
|  | ||||
| @ -23,7 +23,7 @@ class SubscriptionFactory | ||||
|         $billing_subscription->company_id = $company_id; | ||||
|         $billing_subscription->user_id = $user_id; | ||||
|         $billing_subscription->steps = collect(Purchase::defaultSteps()) | ||||
|             ->map(fn($step) => StepService::mapClassNameToString($step)) | ||||
|             ->map(fn ($step) => StepService::mapClassNameToString($step)) | ||||
|             ->implode(','); | ||||
| 
 | ||||
|         return $billing_subscription; | ||||
|  | ||||
| @ -20,7 +20,7 @@ class TaxRateFactory | ||||
|         $tax_rate = new TaxRate(); | ||||
| 
 | ||||
|         $tax_rate->name = ''; | ||||
|         $tax_rate->rate = ''; | ||||
|         $tax_rate->rate = 0; | ||||
|         $tax_rate->company_id = $company_id; | ||||
|         $tax_rate->user_id = $user_id; | ||||
| 
 | ||||
|  | ||||
| @ -26,7 +26,7 @@ class VendorFactory | ||||
|         $vendor->private_notes = ''; | ||||
|         $vendor->public_notes = ''; | ||||
|         $vendor->country_id = 4; | ||||
|         $vendor->is_deleted = 0; | ||||
|         $vendor->is_deleted = false; | ||||
|         $vendor->vendor_hash = Str::random(40); | ||||
|         // $vendor->classification = '';
 | ||||
| 
 | ||||
|  | ||||
| @ -115,6 +115,29 @@ class BankTransactionFilters extends QueryFilters | ||||
|         return $this->builder; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Filters the list based on Bank Accounts. | ||||
|      * | ||||
|      * @param string $ids Comma Separated List of bank account ids | ||||
|      * @return Builder | ||||
|      */ | ||||
|     public function bank_integration_ids(string $ids = ''): Builder | ||||
|     { | ||||
|         if(strlen($ids) == 0) { | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|         $ids = $this->transformKeys(explode(",", $ids)); | ||||
| 
 | ||||
|         $this->builder->where(function ($query) use ($ids) { | ||||
|             $query->whereIn('bank_integration_id', $ids); | ||||
|         }); | ||||
| 
 | ||||
|         return $this->builder; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Sorts the list based on $sort. | ||||
|      * | ||||
|  | ||||
| @ -160,8 +160,9 @@ class ClientFilters extends QueryFilters | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|         if($sort_col[0] == 'documents') | ||||
|         if($sort_col[0] == 'documents') { | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|         if ($sort_col[0] == 'display_name') { | ||||
|             $sort_col[0] = 'name'; | ||||
|  | ||||
| @ -58,10 +58,11 @@ class DesignFilters extends QueryFilters | ||||
| 
 | ||||
|     public function entities(string $entities = ''): Builder | ||||
|     { | ||||
|      | ||||
|         if(stripos($entities, 'statement') !== false) | ||||
| 
 | ||||
|         if(stripos($entities, 'statement') !== false) { | ||||
|             $entities = 'client'; | ||||
|       | ||||
|         } | ||||
| 
 | ||||
|         if (strlen($entities) == 0 || str_contains($entities, ',')) { | ||||
|             return $this->builder; | ||||
|         } | ||||
|  | ||||
| @ -49,22 +49,22 @@ class DocumentFilters extends QueryFilters | ||||
|      */ | ||||
|     public function client_id(string $client_id = ''): Builder | ||||
|     { | ||||
|          | ||||
| 
 | ||||
|         return $this->builder->where(function ($query) use ($client_id) { | ||||
|             $query->whereHasMorph('documentable', [ | ||||
|                 \App\Models\Invoice::class,  | ||||
|                 \App\Models\Quote::class,  | ||||
|                 \App\Models\Credit::class,  | ||||
|                 \App\Models\Expense::class,  | ||||
|                 \App\Models\Payment::class,  | ||||
|                 \App\Models\Invoice::class, | ||||
|                 \App\Models\Quote::class, | ||||
|                 \App\Models\Credit::class, | ||||
|                 \App\Models\Expense::class, | ||||
|                 \App\Models\Payment::class, | ||||
|                 \App\Models\Task::class, | ||||
|                 \App\Models\RecurringExpense::class, | ||||
|                 \App\Models\RecurringInvoice::class, | ||||
|                 \App\Models\Project::class, | ||||
|             ], function ($q2) use ($client_id) { | ||||
|                         $q2->where('client_id', $this->decodePrimaryKey($client_id)); | ||||
|                 })->orWhereHasMorph('documentable', [\App\Models\Client::class], function ($q3) use ($client_id) { | ||||
|                         $q3->where('id', $this->decodePrimaryKey($client_id)); | ||||
|                 $q2->where('client_id', $this->decodePrimaryKey($client_id)); | ||||
|             })->orWhereHasMorph('documentable', [\App\Models\Client::class], function ($q3) use ($client_id) { | ||||
|                 $q3->where('id', $this->decodePrimaryKey($client_id)); | ||||
|             }); | ||||
|         }); | ||||
| 
 | ||||
| @ -74,8 +74,7 @@ class DocumentFilters extends QueryFilters | ||||
|     { | ||||
|         $types = explode(',', $types); | ||||
| 
 | ||||
|         foreach ($types as $type) | ||||
|         { | ||||
|         foreach ($types as $type) { | ||||
|             match($type) { | ||||
|                 'private' => $this->builder->where('is_public', 0), | ||||
|                 'public' => $this->builder->where('is_public', 1), | ||||
| @ -87,7 +86,7 @@ class DocumentFilters extends QueryFilters | ||||
|         } | ||||
| 
 | ||||
|         return $this->builder; | ||||
|     }  | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Sorts the list based on $sort. | ||||
|  | ||||
| @ -79,7 +79,7 @@ class ExpenseFilters extends QueryFilters | ||||
|         $this->builder->where(function ($query) use ($status_parameters) { | ||||
|             if (in_array('logged', $status_parameters)) { | ||||
|                 $query->orWhere(function ($query) { | ||||
|                     $query->where('amount', '>', 0) | ||||
|                     $query->where('amount', '>=', 0) | ||||
|                           ->whereNull('invoice_id') | ||||
|                           ->whereNull('payment_date') | ||||
|                           ->where('should_be_invoiced', false); | ||||
| @ -111,8 +111,8 @@ class ExpenseFilters extends QueryFilters | ||||
|                 }); | ||||
|             } | ||||
| 
 | ||||
|             if(in_array('uncategorized', $status_parameters)){ | ||||
|                 $query->orWhere(function ($query){ | ||||
|             if(in_array('uncategorized', $status_parameters)) { | ||||
|                 $query->orWhere(function ($query) { | ||||
|                     $query->whereNull('category_id'); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
| @ -152,22 +152,22 @@ class InvoiceFilters extends QueryFilters | ||||
|     { | ||||
| 
 | ||||
|         return $this->builder->where(function ($query) { | ||||
|             $query->whereIn('status_id', [Invoice::STATUS_PARTIAL, Invoice::STATUS_SENT]) | ||||
|             ->where('is_deleted', 0) | ||||
|             ->where('balance', '>', 0) | ||||
|             ->where(function ($query) { | ||||
|             $query->whereIn('invoices.status_id', [Invoice::STATUS_PARTIAL, Invoice::STATUS_SENT]) | ||||
|             ->where('invoices.is_deleted', 0) | ||||
|             ->where('invoices.balance', '>', 0) | ||||
|             ->orWhere(function ($query) { | ||||
| 
 | ||||
|                 $query->whereNull('due_date') | ||||
|                 $query->whereNull('invoices.due_date') | ||||
|                     ->orWhere(function ($q) { | ||||
|                         $q->where('due_date', '>=', now()->startOfDay()->subSecond())->where('partial', 0); | ||||
|                         $q->where('invoices.due_date', '>=', now()->startOfDay()->subSecond())->where('invoices.partial', 0); | ||||
|                     }) | ||||
|                     ->orWhere(function ($q) { | ||||
|                         $q->where('partial_due_date', '>=', now()->startOfDay()->subSecond())->where('partial', '>', 0); | ||||
|                         $q->where('invoices.partial_due_date', '>=', now()->startOfDay()->subSecond())->where('invoices.partial', '>', 0); | ||||
|                     }); | ||||
| 
 | ||||
|             }) | ||||
|             ->orderByRaw('ISNULL(due_date), due_date ' . 'desc') | ||||
|             ->orderByRaw('ISNULL(partial_due_date), partial_due_date ' . 'desc'); | ||||
|             ->orderByRaw('ISNULL(invoices.due_date), invoices.due_date ' . 'desc') | ||||
|             ->orderByRaw('ISNULL(invoices.partial_due_date), invoices.partial_due_date ' . 'desc'); | ||||
|         }); | ||||
| 
 | ||||
|     } | ||||
| @ -228,10 +228,9 @@ class InvoiceFilters extends QueryFilters | ||||
|             $date = Carbon::createFromTimestamp((int)$date); | ||||
|         } else { | ||||
| 
 | ||||
|             try{ | ||||
|             try { | ||||
|                 $date = Carbon::parse($date); | ||||
|             } | ||||
|             catch(\Exception $e){ | ||||
|             } catch(\Exception $e) { | ||||
|                 return $this->builder; | ||||
|             } | ||||
|         } | ||||
| @ -272,6 +271,7 @@ class InvoiceFilters extends QueryFilters | ||||
|         if (count($parts) != 2) { | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
| 
 | ||||
|             $start_date = Carbon::parse($parts[0]); | ||||
| @ -282,7 +282,6 @@ class InvoiceFilters extends QueryFilters | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|         return $this->builder; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -308,7 +307,6 @@ class InvoiceFilters extends QueryFilters | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|         return $this->builder; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| @ -322,7 +320,7 @@ class InvoiceFilters extends QueryFilters | ||||
|     { | ||||
|         $sort_col = explode('|', $sort); | ||||
| 
 | ||||
|         if (!is_array($sort_col) || count($sort_col) != 2) { | ||||
|         if (!is_array($sort_col) || count($sort_col) != 2 || in_array($sort_col[0], ['documents'])) { | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
| @ -339,10 +337,10 @@ class InvoiceFilters extends QueryFilters | ||||
|             // return $this->builder->orderByRaw('CAST(number AS UNSIGNED), number ' . $dir);
 | ||||
|             // return $this->builder->orderByRaw("number REGEXP '^[A-Za-z]+$',CAST(number as SIGNED INTEGER),CAST(REPLACE(number,'-','')AS SIGNED INTEGER) ,number");
 | ||||
|             // return $this->builder->orderByRaw('ABS(number) ' . $dir);
 | ||||
|                return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir); | ||||
|             return $this->builder->orderByRaw("REGEXP_REPLACE(invoices.number,'[^0-9]+','')+0 " . $dir); | ||||
|         } | ||||
| 
 | ||||
|         return $this->builder->orderBy($sort_col[0], $dir); | ||||
|         return $this->builder->orderBy("{$this->builder->getQuery()->from}.".$sort_col[0], $dir); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -204,7 +204,6 @@ class PaymentFilters extends QueryFilters | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|         return $this->builder; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -133,7 +133,11 @@ class RecurringInvoiceFilters extends QueryFilters | ||||
|             return $this->builder->orderByRaw("REGEXP_REPLACE(number,'[^0-9]+','')+0 " . $dir); | ||||
|         } | ||||
| 
 | ||||
|         if($sort_col[0] == 'next_send_datetime'){ | ||||
|         if($sort_col[0] == 'status_id'){ | ||||
|             return $this->builder->orderBy('status_id', $dir)->orderBy('last_sent_date', $dir); | ||||
|         } | ||||
| 
 | ||||
|         if($sort_col[0] == 'next_send_datetime') { | ||||
|             $sort_col[0] = 'next_send_date'; | ||||
|         } | ||||
| 
 | ||||
| @ -162,9 +166,10 @@ class RecurringInvoiceFilters extends QueryFilters | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|         /** @var array $key_parameters */ | ||||
|         $key_parameters = explode(',', $value); | ||||
| 
 | ||||
|         if (count($key_parameters)) { | ||||
|         if (count($key_parameters) > 0) { | ||||
|             return $this->builder->where(function ($query) use ($key_parameters) { | ||||
|                 foreach ($key_parameters as $key) { | ||||
|                     $query->orWhereJsonContains('line_items', ['product_key' => $key]); | ||||
| @ -183,6 +188,7 @@ class RecurringInvoiceFilters extends QueryFilters | ||||
|      */ | ||||
|     public function next_send_between(string $range = ''): Builder | ||||
|     { | ||||
|         /** @var array $parts */ | ||||
|         $parts = explode('|', $range); | ||||
| 
 | ||||
|         if (!isset($parts[0]) || !isset($parts[1])) { | ||||
|  | ||||
| @ -88,7 +88,7 @@ class TaskFilters extends QueryFilters | ||||
|         return $this->builder; | ||||
|     } | ||||
| 
 | ||||
|     public function project_tasks($project): Builder | ||||
|     public function project_tasks(string $project = ''): Builder | ||||
|     { | ||||
|         if (strlen($project) == 0) { | ||||
|             return $this->builder; | ||||
| @ -175,6 +175,7 @@ class TaskFilters extends QueryFilters | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|         /** @var array $status_parameters */ | ||||
|         $status_parameters = explode(',', $value); | ||||
| 
 | ||||
|         if(count($status_parameters) >= 1) { | ||||
|  | ||||
| @ -46,7 +46,7 @@ class WebhookFilters extends QueryFilters | ||||
|     { | ||||
|         $sort_col = explode('|', $sort); | ||||
| 
 | ||||
|         if (!is_array($sort_col) || count($sort_col) != 2) { | ||||
|         if (!is_array($sort_col) || count($sort_col) != 2 || !in_array($sort_col[0], \Illuminate\Support\Facades\Schema::getColumnListing('webhooks'))) { | ||||
|             return $this->builder; | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -24,9 +24,10 @@ use App\Services\Email\Email; | ||||
| use App\Models\BankIntegration; | ||||
| use App\Services\Email\EmailObject; | ||||
| use Illuminate\Support\Facades\App; | ||||
| use Illuminate\Support\Facades\Cache; | ||||
| use Illuminate\Mail\Mailables\Address; | ||||
| use App\Helpers\Bank\Nordigen\Transformer\AccountTransformer; | ||||
| use App\Helpers\Bank\Nordigen\Transformer\TransactionTransformer; | ||||
| use Illuminate\Mail\Mailables\Address; | ||||
| 
 | ||||
| class Nordigen | ||||
| { | ||||
| @ -99,7 +100,7 @@ class Nordigen | ||||
|         } catch (\Exception $e) { | ||||
| 
 | ||||
|             nlog("Nordigen getAccount() failed => {$account_id} => " . $e->getMessage()); | ||||
|              | ||||
| 
 | ||||
|             return false; | ||||
| 
 | ||||
|         } | ||||
| @ -149,6 +150,11 @@ class Nordigen | ||||
| 
 | ||||
|     public function disabledAccountEmail(BankIntegration $bank_integration): void | ||||
|     { | ||||
|         $cache_key = "email_quota:{$bank_integration->company->company_key}:{$bank_integration->id}"; | ||||
| 
 | ||||
|         if(Cache::has($cache_key)) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         App::setLocale($bank_integration->company->getLocale()); | ||||
| 
 | ||||
| @ -164,6 +170,7 @@ class Nordigen | ||||
| 
 | ||||
|         Email::dispatch($mo, $bank_integration->company); | ||||
| 
 | ||||
|         Cache::put($cache_key, true, 60 * 60 * 24); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -71,7 +71,7 @@ class TransactionTransformer implements BankRevenueInterface | ||||
| 
 | ||||
|     private Company $company; | ||||
| 
 | ||||
|     function __construct(Company $company) | ||||
|     public function __construct(Company $company) | ||||
|     { | ||||
|         $this->company = $company; | ||||
|     } | ||||
| @ -156,22 +156,16 @@ class TransactionTransformer implements BankRevenueInterface | ||||
|     private function convertCurrency(string $code) | ||||
|     { | ||||
| 
 | ||||
|         $currencies = Cache::get('currencies'); | ||||
|         $currencies = app('currencies'); | ||||
| 
 | ||||
|         if (!$currencies) { | ||||
|             $this->buildCache(true); | ||||
|         } | ||||
| 
 | ||||
|         $currency = $currencies->filter(function ($item) use ($code) { | ||||
|         $currency = $currencies->first(function ($item) use ($code) { | ||||
|             /** @var \App\Models\Currency $item */ | ||||
|             return $item->code == $code; | ||||
|         })->first(); | ||||
| 
 | ||||
|         if ($currency) { | ||||
|             return $currency->id; | ||||
|         } | ||||
| 
 | ||||
|         return 1; | ||||
|         }); | ||||
| 
 | ||||
|         /** @var \App\Models\Currency $currency */ | ||||
|         return $currency ? $currency->id : 1; //@phpstan-ignore-line
 | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|     private function formatDate(string $input) | ||||
| @ -192,7 +186,7 @@ class TransactionTransformer implements BankRevenueInterface | ||||
|         } | ||||
| 
 | ||||
|         try { | ||||
|            return Carbon::createFromFormat("d-m-Y", $input)->setTimezone($timezone_name)->format($date_format_default) ?? $input; | ||||
|             return Carbon::createFromFormat("d-m-Y", $input)->setTimezone($timezone_name)->format($date_format_default); | ||||
|         } catch (\Exception $e) { | ||||
|             return $input; | ||||
|         } | ||||
|  | ||||
| @ -1,111 +0,0 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Invoice Ninja (https://invoiceninja.com). | ||||
|  * | ||||
|  * @link https://github.com/invoiceninja/invoiceninja source repository | ||||
|  * | ||||
|  * @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com) | ||||
|  * | ||||
|  * @license https://www.elastic.co/licensing/elastic-license | ||||
|  */ | ||||
| 
 | ||||
| namespace App\Helpers\Bank\Yodlee\DTO; | ||||
| 
 | ||||
| use Illuminate\Support\Collection; | ||||
| use Spatie\LaravelData\Attributes\MapInputName; | ||||
| use Spatie\LaravelData\Data; | ||||
| 
 | ||||
| /** | ||||
|  * @deprecated | ||||
|  * [ | ||||
|     "account": [ | ||||
|       [ | ||||
|         "CONTAINER": "bank", | ||||
|         "providerAccountId": 1005, | ||||
|         "accountName": "Business Acct", | ||||
|         "accountStatus": "ACTIVE", | ||||
|         "accountNumber": "1011", | ||||
|         "aggregationSource": "USER", | ||||
|         "isAsset": true, | ||||
|         "balance": [ | ||||
|           "currency": "AUD", | ||||
|           "amount": 304.98, | ||||
|         ], | ||||
|         "id": 10139315, | ||||
|         "includeInNetWorth": true, | ||||
|         "providerId": "3857", | ||||
|         "providerName": "Bank", | ||||
|         "isManual": false, | ||||
|         "availableBalance": {#2966
 | ||||
|           "currency": "AUD", | ||||
|           "amount": 304.98, | ||||
|         ], | ||||
|         "currentBalance": [ | ||||
|           "currency": "AUD", | ||||
|           "amount": 3044.98, | ||||
|         ], | ||||
|         "accountType": "CHECKING", | ||||
|         "displayedName": "after David", | ||||
|         "createdDate": "2023-01-10T08:29:07Z", | ||||
|         "classification": "SMALL_BUSINESS", | ||||
|         "lastUpdated": "2023-08-01T23:50:13Z", | ||||
|         "nickname": "Business ", | ||||
|         "bankTransferCode": [ | ||||
|           [ | ||||
|             "id": "062", | ||||
|             "type": "BSB", | ||||
|           ], | ||||
|         ], | ||||
|         "dataset": [ | ||||
|           [ | ||||
|             "name": "BASIC_AGG_DATA", | ||||
|             "additionalStatus": "AVAILABLE_DATA_RETRIEVED", | ||||
|             "updateEligibility": "ALLOW_UPDATE", | ||||
|             "lastUpdated": "2023-08-01T23:49:53Z", | ||||
|             "lastUpdateAttempt": "2023-08-01T23:49:53Z", | ||||
|             "nextUpdateScheduled": "2023-08-03T14:45:14Z", | ||||
|           ], | ||||
|         ], | ||||
|       ], | ||||
|     ], | ||||
|   ]; | ||||
|  */ | ||||
| class AccountSummary extends Data | ||||
| { | ||||
|     public ?int $id; | ||||
| 
 | ||||
|     #[MapInputName('CONTAINER')]
 | ||||
|     public ?string $account_type = ''; | ||||
| 
 | ||||
|     #[MapInputName('accountName')]
 | ||||
|     public ?string $account_name = ''; | ||||
| 
 | ||||
|     #[MapInputName('accountStatus')]
 | ||||
|     public ?string $account_status = ''; | ||||
| 
 | ||||
|     #[MapInputName('accountNumber')]
 | ||||
|     public ?string $account_number = ''; | ||||
| 
 | ||||
|     #[MapInputName('providerAccountId')]
 | ||||
|     public int $provider_account_id; | ||||
| 
 | ||||
|     #[MapInputName('providerId')]
 | ||||
|     public ?string $provider_id = ''; | ||||
| 
 | ||||
|     #[MapInputName('providerName')]
 | ||||
|     public ?string $provider_name = ''; | ||||
| 
 | ||||
|     public ?string $nickname = ''; | ||||
| 
 | ||||
|     public ?float $current_balance = 0; | ||||
|     public ?string $account_currency = ''; | ||||
| 
 | ||||
|     public static function prepareForPipeline(Collection $properties): Collection | ||||
|     { | ||||
| 
 | ||||
|         $properties->put('current_balance', $properties['currentBalance']['amount'] ?? 0); | ||||
|         $properties->put('account_currency', $properties['currentBalance']['currency'] ?? 0); | ||||
| 
 | ||||
|         return $properties; | ||||
|     } | ||||
| } | ||||
| @ -171,20 +171,16 @@ class IncomeTransformer implements BankRevenueInterface | ||||
| 
 | ||||
|     private function convertCurrency(string $code) | ||||
|     { | ||||
|         $currencies = Cache::get('currencies'); | ||||
| 
 | ||||
|         if (! $currencies) { | ||||
|             $this->buildCache(true); | ||||
|         } | ||||
|         $currencies = app('currencies'); | ||||
| 
 | ||||
|         $currency = $currencies->filter(function ($item) use ($code) { | ||||
|         $currency = $currencies->first(function ($item) use ($code) { | ||||
|             /** @var \App\Models\Currency $item */ | ||||
|             return $item->code == $code; | ||||
|         })->first(); | ||||
|         }); | ||||
| 
 | ||||
|         if ($currency) { | ||||
|             return $currency->id; | ||||
|         } | ||||
|         /** @var \App\Models\Currency $currency */ | ||||
|         return $currency ? $currency->id : 1; //@phpstan-ignore-line
 | ||||
| 
 | ||||
|         return 1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -26,15 +26,15 @@ use BaconQrCode\Writer; | ||||
|  */ | ||||
| class EpcQrGenerator | ||||
| { | ||||
|     private array $sepa = [ | ||||
|         'serviceTag' => 'BCD', | ||||
|         'version' => 2, | ||||
|         'characterSet' => 1, | ||||
|         'identification' => 'SCT', | ||||
|         'bic' => '', | ||||
|         'purpose' => '', | ||||
|     // private array $sepa = [
 | ||||
|     //     'serviceTag' => 'BCD',
 | ||||
|     //     'version' => 2,
 | ||||
|     //     'characterSet' => 1,
 | ||||
|     //     'identification' => 'SCT',
 | ||||
|     //     'bic' => '',
 | ||||
|     //     'purpose' => '',
 | ||||
| 
 | ||||
|     ]; | ||||
|     // ];
 | ||||
| 
 | ||||
|     public function __construct(protected Company $company, protected Invoice|RecurringInvoice $invoice, protected float $amount) | ||||
|     { | ||||
| @ -59,36 +59,47 @@ class EpcQrGenerator | ||||
|           <rect x='0' y='0' width='100%'' height='100%' />{$qr}</svg>";
 | ||||
| 
 | ||||
|         } catch(\Throwable $e) { | ||||
|             // nlog("EPC QR failure => ".$e->getMessage());
 | ||||
|             nlog("EPC QR failure => ".$e->getMessage()); | ||||
|             return ''; | ||||
|         } catch(\Exception $e) { | ||||
|             // nlog("EPC QR failure => ".$e->getMessage());
 | ||||
|             return ''; | ||||
|         } catch(InvalidArgumentException $e) { | ||||
|             // nlog("EPC QR failure => ".$e->getMessage());
 | ||||
|             return ''; | ||||
|         } | ||||
|         }  | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public function encodeMessage() | ||||
|     { | ||||
|         return rtrim(implode("\n", [ | ||||
|             $this->sepa['serviceTag'], | ||||
|             sprintf('%03d', $this->sepa['version']), | ||||
|             $this->sepa['characterSet'], | ||||
|             $this->sepa['identification'], | ||||
|             isset($this->company?->custom_fields?->company2) ? $this->company->settings->custom_value2 : '', | ||||
|             $this->company->present()->name(), | ||||
|             isset($this->company?->custom_fields?->company1) ? $this->company->settings->custom_value1 : '', | ||||
|             $this->formatMoney($this->amount), | ||||
|             $this->sepa['purpose'], | ||||
|             substr($this->invoice->number, 0, 34), | ||||
|             '', | ||||
|             ' ' | ||||
|         ]), "\n"); | ||||
|         // return rtrim(implode("\n", [
 | ||||
|         //     $this->sepa['serviceTag'],
 | ||||
|         //     sprintf('%03d', $this->sepa['version']),
 | ||||
|         //     $this->sepa['characterSet'],
 | ||||
|         //     $this->sepa['identification'],
 | ||||
|         //     isset($this->company?->custom_fields?->company2) ? $this->company->settings->custom_value2 : '',
 | ||||
|         //     $this->company->present()->name(),
 | ||||
|         //     isset($this->company?->custom_fields?->company1) ? $this->company->settings->custom_value1 : '',
 | ||||
|         //     $this->formatMoney($this->amount),
 | ||||
|         //     $this->sepa['purpose'],
 | ||||
|         //     substr($this->invoice->number, 0, 34),
 | ||||
|         //     '',
 | ||||
|         //     ' '
 | ||||
|         // ]), "\n");
 | ||||
| 
 | ||||
| 
 | ||||
|         $data = [ | ||||
|             'BCD', | ||||
|             '002', // Version
 | ||||
|             '1', // Encoding: 1 = UTF-8
 | ||||
|             'SCT', // Service Tag: SEPA Credit Transfer
 | ||||
|             isset($this->company?->custom_fields?->company2) ? $this->company->settings->custom_value2 : '', // BIC
 | ||||
|             $this->company->present()->name(), // Name of the beneficiary
 | ||||
|             isset($this->company?->custom_fields?->company1) ? $this->company->settings->custom_value1 : '', // IBAN
 | ||||
|             $this->formatMoney($this->amount), // Amount with EUR prefix
 | ||||
|             '', // Reference
 | ||||
|             substr($this->invoice->number, 0, 34) // Unstructured remittance information
 | ||||
|         ]; | ||||
| 
 | ||||
|         return implode("\n", $data); | ||||
| 
 | ||||
|     } | ||||
|      | ||||
| 
 | ||||
| 
 | ||||
|     //            substr("{$this->invoice->number} {$this->invoice->client->number}", 0,139),
 | ||||
| 
 | ||||
|  | ||||
| @ -27,7 +27,7 @@ trait CustomValuer | ||||
| 
 | ||||
|     public function valuerTax($custom_value, $has_custom_invoice_taxes) | ||||
|     { | ||||
|          | ||||
| 
 | ||||
|         if (isset($custom_value) && is_numeric($custom_value) && $has_custom_invoice_taxes !== false) { | ||||
|             return round($custom_value * ($this->invoice->tax_rate1 / 100), 2) + round($custom_value * ($this->invoice->tax_rate2 / 100), 2) + round($custom_value * ($this->invoice->tax_rate3 / 100), 2); | ||||
|         } | ||||
| @ -35,17 +35,18 @@ trait CustomValuer | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     public function multiInclusiveTax($custom_value, $has_custom_invoice_taxes) { | ||||
|     public function multiInclusiveTax($custom_value, $has_custom_invoice_taxes) | ||||
|     { | ||||
| 
 | ||||
|         if (isset($custom_value) && is_numeric($custom_value) && $has_custom_invoice_taxes !== false) { | ||||
| 
 | ||||
|                 $tax = 0; | ||||
|             $tax = 0; | ||||
| 
 | ||||
|                 $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate1 / 100))), 2); | ||||
|                 $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate2 / 100))), 2); | ||||
|                 $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate3 / 100))), 2); | ||||
|             $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate1 / 100))), 2); | ||||
|             $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate2 / 100))), 2); | ||||
|             $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate3 / 100))), 2); | ||||
| 
 | ||||
|                 return round($tax,2); | ||||
|             return round($tax, 2); | ||||
|         } | ||||
| 
 | ||||
|         return 0; | ||||
|  | ||||
| @ -29,6 +29,7 @@ class InvoiceItemSum | ||||
|     use Discounter; | ||||
|     use Taxer; | ||||
| 
 | ||||
|     //@phpstan-ignore-next-line
 | ||||
|     private array $eu_tax_jurisdictions = [ | ||||
|         'AT', // Austria
 | ||||
|         'BE', // Belgium
 | ||||
| @ -170,7 +171,7 @@ class InvoiceItemSum | ||||
|     private function shouldCalculateTax(): self | ||||
|     { | ||||
| 
 | ||||
|         if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) { | ||||
|         if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) { //@phpstan-ignore-line
 | ||||
|             $this->calc_tax = false; | ||||
|             return $this; | ||||
|         } | ||||
| @ -182,7 +183,7 @@ class InvoiceItemSum | ||||
|             $class = "App\DataMapper\Tax\\".$this->client->company->country()->iso_3166_2."\\Rule"; | ||||
| 
 | ||||
|             $this->rule = new $class(); | ||||
|              | ||||
| 
 | ||||
|             if($this->rule->regionWithNoTaxCoverage($this->client->country->iso_3166_2)) { | ||||
|                 return $this; | ||||
|             } | ||||
| @ -331,7 +332,7 @@ class InvoiceItemSum | ||||
| 
 | ||||
|     public function setLineTotal($total) | ||||
|     { | ||||
|         $this->item->line_total = $total; | ||||
|         $this->item->line_total = (float) $total; | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
| @ -27,7 +27,7 @@ class InvoiceItemSumInclusive | ||||
|     use Discounter; | ||||
|     use Taxer; | ||||
| 
 | ||||
| 
 | ||||
|     //@phpstan-ignore-next-line
 | ||||
|     private array $eu_tax_jurisdictions = [ | ||||
|         'AT', // Austria
 | ||||
|         'BE', // Belgium
 | ||||
| @ -98,6 +98,7 @@ class InvoiceItemSumInclusive | ||||
| 
 | ||||
|     private $total_taxes; | ||||
| 
 | ||||
|     /** @phpstan-ignore-next-line */ | ||||
|     private $item; | ||||
| 
 | ||||
|     private $line_items; | ||||
| @ -399,7 +400,7 @@ class InvoiceItemSumInclusive | ||||
|     private function shouldCalculateTax(): self | ||||
|     { | ||||
| 
 | ||||
|         if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) { | ||||
|         if (!$this->invoice->company?->calculate_taxes || $this->invoice->company->account->isFreeHostedClient()) {//@phpstan-ignore-line
 | ||||
|             $this->calc_tax = false; | ||||
|             return $this; | ||||
|         } | ||||
|  | ||||
| @ -229,7 +229,7 @@ class InvoiceSum | ||||
|     { | ||||
|         // $this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision);
 | ||||
|         // $this->invoice->total_taxes = $this->getTotalTaxes();
 | ||||
|          | ||||
| 
 | ||||
|         $this->setCalculatedAttributes(); | ||||
|         $this->invoice->balance = $this->invoice->amount; | ||||
|         $this->invoice->saveQuietly(); | ||||
| @ -245,10 +245,9 @@ class InvoiceSum | ||||
|      */ | ||||
|     private function setCalculatedAttributes(): self | ||||
|     { | ||||
|         if($this->invoice->status_id == Invoice::STATUS_CANCELLED){ | ||||
|         if($this->invoice->status_id == Invoice::STATUS_CANCELLED) { | ||||
|             $this->invoice->balance = 0; | ||||
|         } | ||||
|         elseif ($this->invoice->status_id != Invoice::STATUS_DRAFT) { | ||||
|         } elseif ($this->invoice->status_id != Invoice::STATUS_DRAFT) { | ||||
|             if ($this->invoice->amount != $this->invoice->balance) { | ||||
|                 $this->invoice->balance = Number::roundValue($this->getTotal(), $this->precision) - $this->invoice->paid_to_date; //21-02-2024 cannot use the calculated $paid_to_date here as it could send the balance backward.
 | ||||
|             } else { | ||||
| @ -258,7 +257,7 @@ class InvoiceSum | ||||
|         /* Set new calculated total */ | ||||
|         $this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision); | ||||
| 
 | ||||
|         if($this->rappen_rounding){ | ||||
|         if($this->rappen_rounding) { | ||||
|             $this->invoice->amount = $this->roundRappen($this->invoice->amount); | ||||
|             $this->invoice->balance = $this->roundRappen($this->invoice->balance); | ||||
|         } | ||||
| @ -269,7 +268,7 @@ class InvoiceSum | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     function roundRappen($value): float | ||||
|     public function roundRappen($value): float | ||||
|     { | ||||
|         return round($value / .05, 0) * .05; | ||||
|     } | ||||
|  | ||||
| @ -107,16 +107,16 @@ class InvoiceSumInclusive | ||||
|     private function calculateCustomValues() | ||||
|     { | ||||
| 
 | ||||
|         $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge1, $this->invoice->custom_surcharge_tax1); | ||||
|         // $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge1, $this->invoice->custom_surcharge_tax1);
 | ||||
|         $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge1); | ||||
| 
 | ||||
|         $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge2, $this->invoice->custom_surcharge_tax2); | ||||
|         // $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge2, $this->invoice->custom_surcharge_tax2);
 | ||||
|         $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge2); | ||||
| 
 | ||||
|         $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge3, $this->invoice->custom_surcharge_tax3); | ||||
|         // $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge3, $this->invoice->custom_surcharge_tax3);
 | ||||
|         $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge3); | ||||
| 
 | ||||
|         $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge4, $this->invoice->custom_surcharge_tax4); | ||||
|         // $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge4, $this->invoice->custom_surcharge_tax4);
 | ||||
|         $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge4); | ||||
| 
 | ||||
|         $this->total += $this->total_custom_values; | ||||
| @ -137,21 +137,21 @@ class InvoiceSumInclusive | ||||
|         } | ||||
| 
 | ||||
|         //Handles cases where the surcharge is not taxed
 | ||||
|         // if(is_numeric($this->invoice->custom_surcharge1) && $this->invoice->custom_surcharge1 > 0 && !$this->invoice->custom_surcharge_tax1) {
 | ||||
|         //     $amount += $this->invoice->custom_surcharge1;
 | ||||
|         // }
 | ||||
|         if(is_numeric($this->invoice->custom_surcharge1) && $this->invoice->custom_surcharge1 > 0 && $this->invoice->custom_surcharge_tax1) { | ||||
|             $amount += $this->invoice->custom_surcharge1; | ||||
|         } | ||||
| 
 | ||||
|         // if(is_numeric($this->invoice->custom_surcharge2) && $this->invoice->custom_surcharge2 > 0 && !$this->invoice->custom_surcharge_tax2) {
 | ||||
|         //     $amount += $this->invoice->custom_surcharge2;
 | ||||
|         // }
 | ||||
|         if(is_numeric($this->invoice->custom_surcharge2) && $this->invoice->custom_surcharge2 > 0 && $this->invoice->custom_surcharge_tax2) { | ||||
|             $amount += $this->invoice->custom_surcharge2; | ||||
|         } | ||||
| 
 | ||||
|         // if(is_numeric($this->invoice->custom_surcharge3) && $this->invoice->custom_surcharge3 > 0 && !$this->invoice->custom_surcharge_tax3) {
 | ||||
|         //     $amount += $this->invoice->custom_surcharge3;
 | ||||
|         // }
 | ||||
|         if(is_numeric($this->invoice->custom_surcharge3) && $this->invoice->custom_surcharge3 > 0 && $this->invoice->custom_surcharge_tax3) { | ||||
|             $amount += $this->invoice->custom_surcharge3; | ||||
|         } | ||||
| 
 | ||||
|         // if(is_numeric($this->invoice->custom_surcharge4) && $this->invoice->custom_surcharge4 > 0 && !$this->invoice->custom_surcharge_tax4) {
 | ||||
|         //     $amount += $this->invoice->custom_surcharge4;
 | ||||
|         // }
 | ||||
|         if(is_numeric($this->invoice->custom_surcharge4) && $this->invoice->custom_surcharge4 > 0 && $this->invoice->custom_surcharge_tax4) { | ||||
|             $amount += $this->invoice->custom_surcharge4; | ||||
|         } | ||||
| 
 | ||||
|         if (is_string($this->invoice->tax_name1) && strlen($this->invoice->tax_name1) > 1) { | ||||
|             $tax = $this->calcInclusiveLineTax($this->invoice->tax_rate1, $amount); | ||||
| @ -171,7 +171,7 @@ class InvoiceSumInclusive | ||||
|             $this->total_taxes += $tax; | ||||
|             $this->total_tax_map[] = ['name' => $this->invoice->tax_name3.' '.floatval($this->invoice->tax_rate3).'%', 'total' => $tax]; | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
| @ -279,10 +279,9 @@ class InvoiceSumInclusive | ||||
|     private function setCalculatedAttributes() | ||||
|     { | ||||
|         /* If amount != balance then some money has been paid on the invoice, need to subtract this difference from the total to set the new balance */ | ||||
|         if($this->invoice->status_id == Invoice::STATUS_CANCELLED){ | ||||
|         if($this->invoice->status_id == Invoice::STATUS_CANCELLED) { | ||||
|             $this->invoice->balance = 0; | ||||
|         } | ||||
|         elseif ($this->invoice->status_id != Invoice::STATUS_DRAFT) { | ||||
|         } elseif ($this->invoice->status_id != Invoice::STATUS_DRAFT) { | ||||
|             if ($this->invoice->amount != $this->invoice->balance) { | ||||
|                 $this->invoice->balance = $this->formatValue($this->getTotal(), $this->precision) - $this->invoice->paid_to_date; | ||||
|             } else { | ||||
| @ -302,8 +301,8 @@ class InvoiceSumInclusive | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
|      | ||||
|     function roundRappen($value): float | ||||
| 
 | ||||
|     public function roundRappen($value): float | ||||
|     { | ||||
|         return round($value / .05, 0) * .05; | ||||
|     } | ||||
| @ -373,7 +372,7 @@ class InvoiceSumInclusive | ||||
| 
 | ||||
|             $this->total_taxes += $total_line_tax; | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         return $this; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -30,7 +30,7 @@ class ProRata | ||||
|      */ | ||||
|     public function refund(float $amount, Carbon $from_date, Carbon $to_date, int $frequency): float | ||||
|     { | ||||
|         $days = $from_date->copy()->diffInDays($to_date); | ||||
|         $days = intval(abs($from_date->copy()->diffInDays($to_date))); | ||||
|         $days_in_frequency = $this->getDaysInFrequency($frequency); | ||||
| 
 | ||||
|         return round((($days / $days_in_frequency) * $amount), 2); | ||||
| @ -48,7 +48,7 @@ class ProRata | ||||
|      */ | ||||
|     public function charge(float $amount, Carbon $from_date, Carbon $to_date, int $frequency): float | ||||
|     { | ||||
|         $days = $from_date->copy()->diffInDays($to_date); | ||||
|         $days = intval(abs($from_date->copy()->diffInDays($to_date))); | ||||
|         $days_in_frequency = $this->getDaysInFrequency($frequency); | ||||
| 
 | ||||
|         return round((($days / $days_in_frequency) * $amount), 2); | ||||
| @ -58,21 +58,21 @@ class ProRata | ||||
|      * Prepares the line items of an invoice | ||||
|      * to be pro rata refunded. | ||||
|      * | ||||
|      * @param Invoice $invoice | ||||
|      * @param ?Invoice $invoice | ||||
|      * @param bool $is_credit | ||||
|      * @return array | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public function refundItems(Invoice $invoice, $is_credit = false): array | ||||
|     public function refundItems(?Invoice $invoice, $is_credit = false): array | ||||
|     { | ||||
|         if (! $invoice) { | ||||
|             return []; | ||||
|         } | ||||
| 
 | ||||
|         /** @var \App\Models\RecurringInvoice $recurring_invoice **/ | ||||
|         $recurring_invoice = RecurringInvoice::find($invoice->recurring_id)->first(); | ||||
|         $recurring_invoice = RecurringInvoice::find($invoice->recurring_id); | ||||
| 
 | ||||
|         if (! $recurring_invoice) { | ||||
|         if (! $recurring_invoice) { // @phpstan-ignore-line
 | ||||
|             throw new \Exception("Invoice isn't attached to a recurring invoice"); | ||||
|         } | ||||
| 
 | ||||
| @ -107,23 +107,23 @@ class ProRata | ||||
|             case RecurringInvoice::FREQUENCY_TWO_WEEKS: | ||||
|                 return 14; | ||||
|             case RecurringInvoice::FREQUENCY_FOUR_WEEKS: | ||||
|                 return now()->diffInDays(now()->addWeeks(4)); | ||||
|                 return intval(abs(now()->diffInDays(now()->addWeeks(4)))); | ||||
|             case RecurringInvoice::FREQUENCY_MONTHLY: | ||||
|                 return now()->diffInDays(now()->addMonthNoOverflow()); | ||||
|                 return intval(abs(now()->diffInDays(now()->addMonthNoOverflow()))); | ||||
|             case RecurringInvoice::FREQUENCY_TWO_MONTHS: | ||||
|                 return now()->diffInDays(now()->addMonthsNoOverflow(2)); | ||||
|                 return intval(abs(now()->diffInDays(now()->addMonthsNoOverflow(2)))); | ||||
|             case RecurringInvoice::FREQUENCY_THREE_MONTHS: | ||||
|                 return now()->diffInDays(now()->addMonthsNoOverflow(3)); | ||||
|                 return intval(abs(now()->diffInDays(now()->addMonthsNoOverflow(3)))); | ||||
|             case RecurringInvoice::FREQUENCY_FOUR_MONTHS: | ||||
|                 return now()->diffInDays(now()->addMonthsNoOverflow(4)); | ||||
|                 return intval(abs(now()->diffInDays(now()->addMonthsNoOverflow(4)))); | ||||
|             case RecurringInvoice::FREQUENCY_SIX_MONTHS: | ||||
|                 return now()->diffInDays(now()->addMonthsNoOverflow(6)); | ||||
|                 return intval(abs(now()->diffInDays(now()->addMonthsNoOverflow(6)))); | ||||
|             case RecurringInvoice::FREQUENCY_ANNUALLY: | ||||
|                 return now()->diffInDays(now()->addYear()); | ||||
|                 return intval(abs(now()->diffInDays(now()->addYear()))); | ||||
|             case RecurringInvoice::FREQUENCY_TWO_YEARS: | ||||
|                 return now()->diffInDays(now()->addYears(2)); | ||||
|                 return intval(abs(now()->diffInDays(now()->addYears(2)))); | ||||
|             case RecurringInvoice::FREQUENCY_THREE_YEARS: | ||||
|                 return now()->diffInDays(now()->addYears(3)); | ||||
|                 return intval(abs(now()->diffInDays(now()->addYears(3)))); | ||||
|             default: | ||||
|                 return 0; | ||||
|         } | ||||
|  | ||||
| @ -34,7 +34,7 @@ class GmailTransport extends AbstractTransport | ||||
|         $message = MessageConverter::toEmail($message->getOriginalMessage()); | ||||
| 
 | ||||
|         /** @phpstan-ignore-next-line **/ | ||||
|         $token = $message->getHeaders()->get('gmailtoken')->getValue(); | ||||
|         $token = $message->getHeaders()->get('gmailtoken')->getValue(); // @phpstan-ignore-line
 | ||||
|         $message->getHeaders()->remove('gmailtoken'); | ||||
| 
 | ||||
|         $client = new Client(); | ||||
| @ -53,9 +53,8 @@ class GmailTransport extends AbstractTransport | ||||
|         if ($bccs) { | ||||
|             $bcc_list = 'Bcc: '; | ||||
| 
 | ||||
|             foreach ($bccs->getAddresses() as $address) {  | ||||
| 
 | ||||
|             /** @phpstan-ignore-next-line **/ | ||||
|             foreach ($bccs->getAddresses() as $address) { | ||||
|                 $bcc_list .= $address->getAddress() .','; | ||||
|             } | ||||
| 
 | ||||
| @ -65,18 +64,18 @@ class GmailTransport extends AbstractTransport | ||||
|         $body->setRaw($this->base64_encode($bcc_list.$message->toString())); | ||||
| 
 | ||||
|         // try {
 | ||||
|             $service->users_messages->send('me', $body, []); | ||||
|         $service->users_messages->send('me', $body, []); | ||||
|         // } catch(\Google\Service\Exception $e) {
 | ||||
|         //     /* Need to slow down */
 | ||||
|         //     if ($e->getCode() == '429') {
 | ||||
|         //         nlog("429 google - retrying ");
 | ||||
| 
 | ||||
|         //         sleep(rand(3,8));
 | ||||
|                  | ||||
| 
 | ||||
|         //         try {
 | ||||
|         //             $service->users_messages->send('me', $body, []);
 | ||||
|         //         } catch(\Google\Service\Exception $e) {
 | ||||
|                  | ||||
| 
 | ||||
|         //         }
 | ||||
| 
 | ||||
|         //     }
 | ||||
|  | ||||
| @ -54,17 +54,17 @@ class Office365MailTransport extends AbstractTransport | ||||
|                 ->setReturnType(\Microsoft\Graph\Model\Message::class) | ||||
|                 ->execute(); | ||||
|         } catch (\Exception $e) { | ||||
|              | ||||
|             sleep(rand(5,10)); | ||||
| 
 | ||||
|             sleep(rand(5, 10)); | ||||
| 
 | ||||
|             try { | ||||
|             $graphMessage = $graph->createRequest('POST', '/users/'.$symfony_message->getFrom()[0]->getAddress().'/sendmail') | ||||
|                 ->attachBody(base64_encode($bcc_list.$message->toString())) | ||||
|                 ->addHeaders(['Content-Type' => 'text/plain']) | ||||
|                 ->setReturnType(\Microsoft\Graph\Model\Message::class) | ||||
|                 ->execute(); | ||||
|                 $graphMessage = $graph->createRequest('POST', '/users/'.$symfony_message->getFrom()[0]->getAddress().'/sendmail') | ||||
|                     ->attachBody(base64_encode($bcc_list.$message->toString())) | ||||
|                     ->addHeaders(['Content-Type' => 'text/plain']) | ||||
|                     ->setReturnType(\Microsoft\Graph\Model\Message::class) | ||||
|                     ->execute(); | ||||
|             } catch (\Exception $e) { | ||||
|              | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|  | ||||
| @ -61,7 +61,7 @@ class AccountController extends BaseController | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param CreateAccountRequest $request | ||||
|      * @return Response | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|      * | ||||
|      */ | ||||
|     public function store(CreateAccountRequest $request) | ||||
| @ -115,13 +115,8 @@ class AccountController extends BaseController | ||||
| 
 | ||||
|     public function update(UpdateAccountRequest $request, Account $account) | ||||
|     { | ||||
|         $fi = new \FilesystemIterator(public_path('react'), \FilesystemIterator::SKIP_DOTS); | ||||
| 
 | ||||
|         if (iterator_count($fi) < 30) { | ||||
|             return response()->json(['message' => 'React App Not Installed, Please install the React app before attempting to switch.'], 400); | ||||
|         } | ||||
| 
 | ||||
|         $account->fill($request->all()); | ||||
|         $account->set_react_as_default_ap = $request->input('set_react_as_default_ap'); | ||||
|         $account->save(); | ||||
| 
 | ||||
|         $this->entity_type = Account::class; | ||||
|  | ||||
| @ -11,19 +11,31 @@ | ||||
| 
 | ||||
| namespace App\Http\Controllers; | ||||
| 
 | ||||
| use App\Http\Requests\Activity\DownloadHistoricalEntityRequest; | ||||
| use App\Http\Requests\Activity\ShowActivityRequest; | ||||
| use App\Models\Activity; | ||||
| use App\Transformers\ActivityTransformer; | ||||
| use App\Utils\HostedPDF\NinjaPdf; | ||||
| use App\Utils\Ninja; | ||||
| use App\Utils\PhantomJS\Phantom; | ||||
| use App\Utils\Traits\MakesHash; | ||||
| use App\Utils\Traits\Pdf\PageNumbering; | ||||
| use App\Utils\Traits\Pdf\PdfMaker; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Storage; | ||||
| use stdClass; | ||||
| use App\Utils\Ninja; | ||||
| use App\Models\Client; | ||||
| use App\Models\Invoice; | ||||
| use App\Models\Activity; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Utils\Traits\MakesHash; | ||||
| use App\Utils\PhantomJS\Phantom; | ||||
| use App\Utils\HostedPDF\NinjaPdf; | ||||
| use App\Utils\Traits\Pdf\PdfMaker; | ||||
| use App\Utils\Traits\Pdf\PageNumbering; | ||||
| use Illuminate\Support\Facades\Storage; | ||||
| use App\Transformers\ActivityTransformer; | ||||
| use App\Http\Requests\Activity\StoreNoteRequest; | ||||
| use App\Http\Requests\Activity\ShowActivityRequest; | ||||
| use App\Http\Requests\Activity\DownloadHistoricalEntityRequest; | ||||
| use App\Models\Credit; | ||||
| use App\Models\Expense; | ||||
| use App\Models\Payment; | ||||
| use App\Models\PurchaseOrder; | ||||
| use App\Models\Quote; | ||||
| use App\Models\RecurringExpense; | ||||
| use App\Models\RecurringInvoice; | ||||
| use App\Models\Task; | ||||
| use App\Models\Vendor; | ||||
| 
 | ||||
| class ActivityController extends BaseController | ||||
| { | ||||
| @ -105,6 +117,14 @@ class ActivityController extends BaseController | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|          | ||||
|     /** | ||||
|      * downloadHistoricalEntity | ||||
|      * | ||||
|      * @param  DownloadHistoricalEntityRequest $request | ||||
|      * @param  Activity $activity | ||||
|      * @return \Symfony\Component\HttpFoundation\StreamedResponse | \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function downloadHistoricalEntity(DownloadHistoricalEntityRequest $request, Activity $activity) | ||||
|     { | ||||
|         $backup = $activity->backup; | ||||
| @ -169,4 +189,89 @@ class ActivityController extends BaseController | ||||
|             echo $pdf; | ||||
|         }, $filename, ['Content-Type' => 'application/pdf']); | ||||
|     } | ||||
| 
 | ||||
|     public function note(StoreNoteRequest $request) | ||||
|     { | ||||
|         /** @var \App\Models\User $user */ | ||||
|         $user = auth()->user(); | ||||
| 
 | ||||
|         $entity = $request->getEntity(); | ||||
| 
 | ||||
|         $activity = new Activity(); | ||||
|         $activity->account_id = $user->account_id; | ||||
|         $activity->company_id = $user->company()->id; | ||||
|         $activity->notes = $request->notes; | ||||
|         $activity->user_id = $user->id; | ||||
|         $activity->ip = $request->ip(); | ||||
|         $activity->activity_type_id = Activity::USER_NOTE; | ||||
|          | ||||
|         switch (get_class($entity)) { | ||||
|             case Invoice::class: | ||||
|                 $activity->invoice_id = $entity->id; | ||||
|                 $activity->client_id = $entity->client_id; | ||||
|                 $activity->project_id = $entity->project_id; | ||||
|                 $activity->vendor_id = $entity->vendor_id; | ||||
|                 break; | ||||
|             case Credit::class: | ||||
|                 $activity->credit_id = $entity->id; | ||||
|                 $activity->client_id = $entity->client_id; | ||||
|                 $activity->project_id = $entity->project_id; | ||||
|                 $activity->vendor_id = $entity->vendor_id; | ||||
|                 $activity->invoice_id = $entity->invoice_id; | ||||
|                 break; | ||||
|             case Client::class: | ||||
|                 $activity->client_id = $entity->id; | ||||
|                 break; | ||||
|             case Quote::class: | ||||
|                 $activity->quote_id = $entity->id; | ||||
|                 $activity->client_id = $entity->client_id; | ||||
|                 $activity->project_id = $entity->project_id; | ||||
|                 $activity->vendor_id = $entity->vendor_id; | ||||
|                 break; | ||||
|             case RecurringInvoice::class: | ||||
|                 $activity->recurring_invoice_id = $entity->id; | ||||
|                 $activity->client_id = $entity->client_id; | ||||
|                 break; | ||||
|             case Expense::class: | ||||
|                 $activity->expense_id = $entity->id; | ||||
|                 $activity->client_id = $entity->client_id; | ||||
|                 $activity->project_id = $entity->project_id; | ||||
|                 $activity->vendor_id = $entity->vendor_id; | ||||
|                 break; | ||||
|             case RecurringExpense::class: | ||||
|                 $activity->recurring_expense_id = $entity->id; | ||||
|                 $activity->expense_id = $entity->id; | ||||
|                 $activity->client_id = $entity->client_id; | ||||
|                 $activity->project_id = $entity->project_id; | ||||
|                 $activity->vendor_id = $entity->vendor_id; | ||||
|                 break; | ||||
|             case Vendor::class: | ||||
|                 $activity->vendor_id = $entity->id; | ||||
|                 break; | ||||
|             case PurchaseOrder::class: | ||||
|                 $activity->purchase_order_id = $entity->id; | ||||
|                 $activity->expense_id = $entity->id; | ||||
|                 $activity->client_id = $entity->client_id; | ||||
|                 $activity->project_id = $entity->project_id; | ||||
|                 $activity->vendor_id = $entity->vendor_id; | ||||
|             case Task::class: | ||||
|                 $activity->task_id = $entity->id; | ||||
|                 $activity->expense_id = $entity->id; | ||||
|                 $activity->client_id = $entity->client_id; | ||||
|                 $activity->project_id = $entity->project_id; | ||||
|                 $activity->vendor_id = $entity->vendor_id; | ||||
|             case Payment::class: | ||||
|                 $activity->payment_id = $entity->id; | ||||
|                 $activity->expense_id = $entity->id; | ||||
|                 $activity->client_id = $entity->client_id; | ||||
|                 $activity->project_id = $entity->project_id; | ||||
|             default: | ||||
|                 # code...
 | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         $activity->save(); | ||||
| 
 | ||||
|         return $this->itemResponse($activity); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -118,7 +118,7 @@ class ContactForgotPasswordController extends Controller | ||||
|                                     })->first(); | ||||
|         } | ||||
| 
 | ||||
|         $response = false; | ||||
|         // $response = false;
 | ||||
| 
 | ||||
|         if ($contact) { | ||||
|             /* Update all instances of the client */ | ||||
| @ -131,16 +131,16 @@ class ContactForgotPasswordController extends Controller | ||||
|         } | ||||
| 
 | ||||
|         if ($request->ajax()) { | ||||
|             if ($response == Password::RESET_THROTTLED) { | ||||
|             if ($response == Password::RESET_THROTTLED) { // @phpstan-ignore-line
 | ||||
|                 return response()->json(['message' => ctrans('passwords.throttled'), 'status' => false], 429); | ||||
|             } | ||||
| 
 | ||||
|             return $response == Password::RESET_LINK_SENT | ||||
|             return $response == Password::RESET_LINK_SENT // @phpstan-ignore-line
 | ||||
|                 ? response()->json(['message' => 'Reset link sent to your email.', 'status' => true], 201) | ||||
|                 : response()->json(['message' => 'Email not found', 'status' => false], 401); | ||||
|         } | ||||
| 
 | ||||
|         return $response == Password::RESET_LINK_SENT | ||||
|         return $response == Password::RESET_LINK_SENT // @phpstan-ignore-line
 | ||||
|             ? $this->sendResetLinkResponse($request, $response) | ||||
|             : $this->sendResetLinkFailedResponse($request, $response); | ||||
|     } | ||||
|  | ||||
| @ -41,6 +41,9 @@ class ContactLoginController extends Controller | ||||
|         $company = false; | ||||
|         $account = false; | ||||
| 
 | ||||
|         if($request->query('intended')) | ||||
|             $request->session()->put('url.intended', $request->query('intended')); | ||||
|          | ||||
|         if ($request->session()->has('company_key')) { | ||||
|             MultiDB::findAndSetDbByCompanyKey($request->session()->get('company_key')); | ||||
|             $company = Company::where('company_key', $request->session()->get('company_key'))->first(); | ||||
| @ -52,7 +55,7 @@ class ContactLoginController extends Controller | ||||
|             $company = Company::where('company_key', $company_key)->first(); | ||||
|         } | ||||
| 
 | ||||
|         /** @var \App\Models\Company $company **/ | ||||
|         /** @var ?\App\Models\Company $company **/ | ||||
|         if ($company) { | ||||
|             $account = $company->account; | ||||
|         } elseif (! $company && strpos($request->getHost(), config('ninja.app_domain')) !== false) { | ||||
| @ -81,6 +84,7 @@ class ContactLoginController extends Controller | ||||
| 
 | ||||
|     public function login(Request $request) | ||||
|     { | ||||
| 
 | ||||
|         Auth::shouldUse('contact'); | ||||
| 
 | ||||
|         if (Ninja::isHosted() && $request->has('company_key')) { | ||||
| @ -125,6 +129,9 @@ class ContactLoginController extends Controller | ||||
| 
 | ||||
|     protected function sendLoginResponse(Request $request) | ||||
|     { | ||||
| 
 | ||||
|         $intended = $request->session()->has('url.intended') ? $request->session()->get('url.intended') : false; | ||||
| 
 | ||||
|         $request->session()->regenerate(); | ||||
| 
 | ||||
|         $this->clearLoginAttempts($request); | ||||
| @ -134,6 +141,9 @@ class ContactLoginController extends Controller | ||||
|         } | ||||
| 
 | ||||
|         $this->setRedirectPath(); | ||||
|          | ||||
|         if($intended) | ||||
|             $this->redirectTo = $intended; | ||||
| 
 | ||||
|         return $request->wantsJson() | ||||
|                     ? new JsonResponse([], 204) | ||||
| @ -146,8 +156,8 @@ class ContactLoginController extends Controller | ||||
| 
 | ||||
|         event(new ContactLoggedIn($client, $client->company, Ninja::eventVars())); | ||||
| 
 | ||||
|         if (session()->get('url.intended')) { | ||||
|             return redirect(session()->get('url.intended')); | ||||
|         if ($request->session()->has('url.intended')) { | ||||
|             return redirect($request->session()->get('url.intended')); | ||||
|         } | ||||
| 
 | ||||
|         $this->setRedirectPath(); | ||||
| @ -165,19 +175,20 @@ class ContactLoginController extends Controller | ||||
| 
 | ||||
|     private function setRedirectPath() | ||||
|     { | ||||
| 
 | ||||
|         if (auth()->guard('contact')->user()->client->getSetting('enable_client_portal_dashboard') === true) { | ||||
|             $this->redirectTo = '/client/dashboard';                                                                                               | ||||
|         } elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES) { | ||||
|             $this->redirectTo = '/client/dashboard'; | ||||
|         } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_INVOICES)) { | ||||
|             $this->redirectTo = '/client/invoices'; | ||||
|         } elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_RECURRING_INVOICES) { | ||||
|         } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_RECURRING_INVOICES)) { | ||||
|             $this->redirectTo = '/client/recurring_invoices'; | ||||
|         } elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES) { | ||||
|         } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_QUOTES)) { | ||||
|             $this->redirectTo = '/client/quotes'; | ||||
|         } elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_CREDITS) { | ||||
|         } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_CREDITS)) { | ||||
|             $this->redirectTo = '/client/credits'; | ||||
|         } elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_TASKS) { | ||||
|         } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_TASKS)) { | ||||
|             $this->redirectTo = '/client/tasks'; | ||||
|         } elseif (auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_EXPENSES) { | ||||
|         } elseif ((bool)(auth()->guard('contact')->user()->company->enabled_modules & PortalComposer::MODULE_EXPENSES)) { | ||||
|             $this->redirectTo = '/client/expenses'; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -50,7 +50,7 @@ class ContactRegisterController extends Controller | ||||
|     public function register(RegisterRequest $request) | ||||
|     { | ||||
|         $request->merge(['company' => $request->company()]); | ||||
|          | ||||
| 
 | ||||
|         $service = new ClientRegisterService( | ||||
|             company: $request->company(), | ||||
|         ); | ||||
|  | ||||
| @ -46,7 +46,7 @@ class ForgotPasswordController extends Controller | ||||
| 
 | ||||
|     /** | ||||
|      * @param Request $request | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse | ||||
|      * @throws \Illuminate\Validation\ValidationException | ||||
|      */ | ||||
|     public function sendResetLinkEmail(Request $request) | ||||
|  | ||||
| @ -13,6 +13,7 @@ | ||||
| namespace App\Http\Controllers\Auth; | ||||
| 
 | ||||
| use App\DataMapper\Analytics\LoginFailure; | ||||
| use App\DataMapper\Analytics\LoginMeta; | ||||
| use App\DataMapper\Analytics\LoginSuccess; | ||||
| use App\Events\User\UserLoggedIn; | ||||
| use App\Http\Controllers\BaseController; | ||||
| @ -111,6 +112,9 @@ class LoginController extends BaseController | ||||
|                 ->increment() | ||||
|                 ->batch(); | ||||
| 
 | ||||
|             LightLogs::create(new LoginMeta($request->email, $request->ip, 'success')) | ||||
|                 ->batch(); | ||||
| 
 | ||||
|             /** @var \App\Models\User $user */ | ||||
|             $user = $this->guard()->user(); | ||||
| 
 | ||||
| @ -159,6 +163,9 @@ class LoginController extends BaseController | ||||
|                 ->increment() | ||||
|                 ->batch(); | ||||
| 
 | ||||
|             LightLogs::create(new LoginMeta($request->email, $request->ip, 'failure')) | ||||
|                 ->batch(); | ||||
| 
 | ||||
|             $this->incrementLoginAttempts($request); | ||||
| 
 | ||||
|             return response() | ||||
| @ -172,7 +179,7 @@ class LoginController extends BaseController | ||||
|      * Refreshes the data feed with the current Company User. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @return Response|JsonResponse | ||||
|      * @return \Illuminate\Http\Response|JsonResponse | ||||
|      */ | ||||
|     public function refresh(Request $request) | ||||
|     { | ||||
| @ -391,8 +398,8 @@ class LoginController extends BaseController | ||||
|         $truth->setCompany($set_company); | ||||
| 
 | ||||
|         //21-03-2024
 | ||||
|         $cu->each(function ($cu){ | ||||
|             if(CompanyToken::where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()){ | ||||
|         $cu->each(function ($cu) { | ||||
|             if(CompanyToken::where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()) { | ||||
|                 (new CreateCompanyToken($cu->company, $cu->user, request()->server('HTTP_USER_AGENT')))->handle(); | ||||
|             } | ||||
|         }); | ||||
| @ -481,7 +488,7 @@ class LoginController extends BaseController | ||||
|      * send login response to oauthed users | ||||
|      * | ||||
|      * @param \App\Models\User $existing_user | ||||
|      * @return Response | JsonResponse | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | JsonResponse | ||||
|      */ | ||||
|     private function existingOauthUser($existing_user) | ||||
|     { | ||||
| @ -651,7 +658,9 @@ class LoginController extends BaseController | ||||
|         } | ||||
| 
 | ||||
|         if(request()->hasHeader('X-REACT') || request()->query('react')) { | ||||
|             Cache::put("react_redir:".auth()->user()?->account->key, 'true', 300); | ||||
|             /**@var \App\Models\User $user */ | ||||
|             $user = auth()->user(); | ||||
|             Cache::put("react_redir:".$user?->account->key, 'true', 300); | ||||
|         } | ||||
| 
 | ||||
|         if (request()->has('code')) { | ||||
|  | ||||
| @ -78,7 +78,7 @@ class ResetPasswordController extends Controller | ||||
|      * Reset the given user's password. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @return RedirectResponse|JsonResponse | ||||
|      * @return \Illuminate\Http\RedirectResponse | \Illuminate\Http\RedirectResponse|JsonResponse | ||||
|      * @throws \Illuminate\Validation\ValidationException | ||||
|      */ | ||||
|     public function reset(Request $request) | ||||
| @ -137,8 +137,8 @@ class ResetPasswordController extends Controller | ||||
|             return redirect('/#/login'); | ||||
|         } | ||||
| 
 | ||||
|         return redirect($this->redirectPath()) | ||||
|                             ->with('status', trans($response)); | ||||
|         // return redirect($this->redirectPath())
 | ||||
|         //                     ->with('status', trans($response));
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -11,7 +11,6 @@ | ||||
| 
 | ||||
| namespace App\Http\Controllers\Bank; | ||||
| 
 | ||||
| use App\Helpers\Bank\Yodlee\DTO\AccountSummary; | ||||
| use App\Helpers\Bank\Yodlee\Yodlee; | ||||
| use App\Http\Controllers\BaseController; | ||||
| use App\Http\Requests\Yodlee\YodleeAdminRequest; | ||||
| @ -301,8 +300,6 @@ class YodleeController extends BaseController | ||||
| 
 | ||||
|         $summary = $yodlee->getAccountSummary($account_number); | ||||
| 
 | ||||
|         //@todo remove laravel-data
 | ||||
|         // $transformed_summary = AccountSummary::from($summary[0]);
 | ||||
|         $transformed_summary = $this->transformSummary($summary[0]); | ||||
| 
 | ||||
|         return response()->json($transformed_summary, 200); | ||||
| @ -310,7 +307,7 @@ class YodleeController extends BaseController | ||||
| 
 | ||||
|     private function transformSummary($summary): array | ||||
|     { | ||||
|         $dto = new \stdClass; | ||||
|         $dto = new \stdClass(); | ||||
|         $dto->id = $summary['id'] ?? 0; | ||||
|         $dto->account_type = $summary['CONTAINER'] ?? ''; | ||||
| 
 | ||||
|  | ||||
| @ -55,7 +55,7 @@ class BankIntegrationController extends BaseController | ||||
| 
 | ||||
|     /** | ||||
|      * @param BankIntegrationFilters $filters | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function index(BankIntegrationFilters $filters) | ||||
|     { | ||||
| @ -69,7 +69,7 @@ class BankIntegrationController extends BaseController | ||||
|      * | ||||
|      * @param ShowBankIntegrationRequest $request | ||||
|      * @param BankIntegration $bank_integration | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function show(ShowBankIntegrationRequest $request, BankIntegration $bank_integration) | ||||
| @ -83,7 +83,7 @@ class BankIntegrationController extends BaseController | ||||
|      * | ||||
|      * @param EditBankIntegrationRequest $request | ||||
|      * @param BankIntegration $bank_integration | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function edit(EditBankIntegrationRequest $request, BankIntegration $bank_integration) | ||||
| @ -96,7 +96,7 @@ class BankIntegrationController extends BaseController | ||||
|      * | ||||
|      * @param UpdateBankIntegrationRequest $request | ||||
|      * @param BankIntegration $bank_integration | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function update(UpdateBankIntegrationRequest $request, BankIntegration $bank_integration) | ||||
| @ -111,7 +111,7 @@ class BankIntegrationController extends BaseController | ||||
|      * Show the form for creating a new resource. | ||||
|      * | ||||
|      * @param CreateBankIntegrationRequest $request | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      * | ||||
|      */ | ||||
| @ -130,7 +130,7 @@ class BankIntegrationController extends BaseController | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param StoreBankIntegrationRequest $request | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function store(StoreBankIntegrationRequest $request) | ||||
| @ -150,7 +150,7 @@ class BankIntegrationController extends BaseController | ||||
|      * | ||||
|      * @param DestroyBankIntegrationRequest $request | ||||
|      * @param BankIntegration $bank_integration | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      * @throws \Exception | ||||
|      */ | ||||
| @ -165,7 +165,7 @@ class BankIntegrationController extends BaseController | ||||
|     /** | ||||
|      * Perform bulk actions on the list view. | ||||
|      * | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function bulk(BulkBankIntegrationRequest $request) | ||||
| @ -270,7 +270,7 @@ class BankIntegrationController extends BaseController | ||||
| 
 | ||||
|         $nordigen = new Nordigen(); | ||||
| 
 | ||||
|         BankIntegration::where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->whereNotNull('nordigen_account_id')->each(function (BankIntegration $bank_integration) use ($nordigen) { | ||||
|         BankIntegration::where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('account_id', $user->account_id)->whereNotNull('nordigen_account_id')->each(function (BankIntegration $bank_integration) use ($nordigen) { | ||||
|             $is_account_active = $nordigen->isAccountActive($bank_integration->nordigen_account_id); | ||||
|             $account = $nordigen->getAccount($bank_integration->nordigen_account_id); | ||||
| 
 | ||||
| @ -295,7 +295,7 @@ class BankIntegrationController extends BaseController | ||||
|      * Return the remote list of accounts stored on the third party provider | ||||
|      * and update our local cache. | ||||
|      * | ||||
|      * @return Response | JsonResponse | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | JsonResponse | ||||
|      * | ||||
|      */ | ||||
| 
 | ||||
|  | ||||
| @ -85,7 +85,7 @@ class BankTransactionRuleController extends BaseController | ||||
|      *       ), | ||||
|      *     ) | ||||
|      * @param BankTransactionRuleFilters $filters | ||||
|      * @return Response|mixed | ||||
|      * @return Response| \Illuminate\Http\JsonResponse|mixed | ||||
|      */ | ||||
|     public function index(BankTransactionRuleFilters $filters) | ||||
|     { | ||||
| @ -99,7 +99,7 @@ class BankTransactionRuleController extends BaseController | ||||
|      * | ||||
|      * @param ShowBankTransactionRuleRequest $request | ||||
|      * @param BankTransactionRule $bank_transaction_rule | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\Illuminate\Http\Response | ||||
|      * | ||||
|      * | ||||
|      * @OA\Get( | ||||
| @ -154,7 +154,7 @@ class BankTransactionRuleController extends BaseController | ||||
|      * | ||||
|      * @param EditBankTransactionRuleRequest $request | ||||
|      * @param BankTransactionRule $bank_transaction_rule | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|      * | ||||
|      * | ||||
|      * @OA\Get( | ||||
| @ -208,7 +208,7 @@ class BankTransactionRuleController extends BaseController | ||||
|      * | ||||
|      * @param UpdateBankTransactionRuleRequest $request | ||||
|      * @param BankTransactionRule $bank_transaction_rule | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|      * | ||||
|      * | ||||
|      * | ||||
| @ -269,7 +269,7 @@ class BankTransactionRuleController extends BaseController | ||||
|      * Show the form for creating a new resource. | ||||
|      * | ||||
|      * @param CreateBankTransactionRuleRequest $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|      * | ||||
|      * | ||||
|      * | ||||
| @ -317,7 +317,7 @@ class BankTransactionRuleController extends BaseController | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param StoreBankTransactionRuleRequest $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|      * | ||||
|      * | ||||
|      * | ||||
| @ -369,7 +369,7 @@ class BankTransactionRuleController extends BaseController | ||||
|      * | ||||
|      * @param DestroyBankTransactionRuleRequest $request | ||||
|      * @param BankTransactionRule $bank_transaction_rule | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|      * | ||||
|      * | ||||
|      * @throws \Exception | ||||
| @ -424,7 +424,7 @@ class BankTransactionRuleController extends BaseController | ||||
|     /** | ||||
|      * Perform bulk actions on the list view. | ||||
|      * | ||||
|      * @return \Illuminate\Support\Collection | ||||
|      * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      * @OA\Post( | ||||
|      *      path="/api/v1/bank_transation_rules/bulk", | ||||
|  | ||||
| @ -38,7 +38,7 @@ use App\Transformers\ArraySerializer; | ||||
| use App\Transformers\EntityTransformer; | ||||
| use League\Fractal\Resource\Collection; | ||||
| use Illuminate\Database\Eloquent\Builder; | ||||
| use Invoiceninja\Einvoice\Decoder\Schema; | ||||
| use InvoiceNinja\EInvoice\Decoder\Schema; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use Illuminate\Contracts\Container\BindingResolutionException; | ||||
| @ -262,7 +262,7 @@ class BaseController extends Controller | ||||
| 
 | ||||
|     /** | ||||
|      * 404 for the client portal. | ||||
|      * @return Response 404 response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse 404 response | ||||
|      */ | ||||
|     public function notFoundClient() | ||||
|     { | ||||
| @ -279,7 +279,7 @@ class BaseController extends Controller | ||||
|      * | ||||
|      * @param string|array    $message        The return error message | ||||
|      * @param int       $httpErrorCode  404/401/403 etc | ||||
|      * @return Response                 The JSON response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse                 The JSON response | ||||
|      * @throws BindingResolutionException | ||||
|      */ | ||||
|     protected function errorResponse($message, $httpErrorCode = 400) | ||||
| @ -297,7 +297,7 @@ class BaseController extends Controller | ||||
|      * Refresh API response with latest cahnges | ||||
|      * | ||||
|      * @param  Builder           $query | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     protected function refreshResponse($query) | ||||
|     { | ||||
| @ -460,7 +460,7 @@ class BaseController extends Controller | ||||
|                     } | ||||
|                 }, | ||||
|                 'company.tasks' => function ($query) use ($updated_at, $user) { | ||||
|                     $query->where('updated_at', '>=', $updated_at)->with('project','documents'); | ||||
|                     $query->where('updated_at', '>=', $updated_at)->with('project', 'documents'); | ||||
| 
 | ||||
|                     if (! $user->hasPermission('view_task')) { | ||||
|                         $query->whereNested(function ($query) use ($user) { | ||||
| @ -798,7 +798,7 @@ class BaseController extends Controller | ||||
|                     } | ||||
|                 }, | ||||
|                 'company.tasks' => function ($query) use ($created_at, $user) { | ||||
|                     $query->where('created_at', '>=', $created_at)->with('project.documents','documents'); | ||||
|                     $query->where('created_at', '>=', $created_at)->with('project.documents', 'documents'); | ||||
| 
 | ||||
|                     if (! $user->hasPermission('view_task')) { | ||||
|                         $query->whereNested(function ($query) use ($user) { | ||||
| @ -937,7 +937,9 @@ class BaseController extends Controller | ||||
|             } elseif (in_array($this->entity_type, [Design::class, GroupSetting::class, PaymentTerm::class, TaskStatus::class])) { | ||||
|                 // nlog($this->entity_type);
 | ||||
|             } else { | ||||
|                 $query->where('user_id', '=', $user->id)->orWhere('assigned_user_id', $user->id); | ||||
|                 $query->where(function ($q) use ($user){ //grouping these together improves query performance significantly)
 | ||||
|                     $q->where('user_id', '=', $user->id)->orWhere('assigned_user_id', $user->id); | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -969,7 +971,7 @@ class BaseController extends Controller | ||||
|      * Sorts the response by keys | ||||
|      * | ||||
|      * @param  mixed $response | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     protected function response($response) | ||||
|     { | ||||
| @ -995,15 +997,16 @@ class BaseController extends Controller | ||||
| 
 | ||||
|                 $response_data = Statics::company($user->getCompany()->getLocale()); | ||||
| 
 | ||||
|                 if(request()->has('einvoice')){ | ||||
| 
 | ||||
|                     $ro = new Schema(); | ||||
|                     $response_data['einvoice_schema'] = $ro('FACT1'); | ||||
|                 if(request()->has('einvoice')) { | ||||
| 
 | ||||
|                     if(class_exists(Schema::class)){ | ||||
|                         $ro = new Schema(); | ||||
|                         $response_data['einvoice_schema'] = $ro('Peppol'); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 $response['static'] = $response_data; | ||||
|                  | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| @ -1020,7 +1023,7 @@ class BaseController extends Controller | ||||
|      * Item Response | ||||
|      * | ||||
|      * @param  mixed $item | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     protected function itemResponse($item) | ||||
|     { | ||||
| @ -1034,7 +1037,7 @@ class BaseController extends Controller | ||||
| 
 | ||||
|         $resource = new Item($item, $transformer, $this->entity_type); | ||||
| 
 | ||||
|         /** @var \App\Models\User $user */ | ||||
|         /** @var ?\App\Models\User $user */ | ||||
|         $user = auth()->user(); | ||||
| 
 | ||||
|         if ($user && request()->include_static) { | ||||
| @ -1157,8 +1160,6 @@ class BaseController extends Controller | ||||
| 
 | ||||
|             $data['path'] = $this->setBuild(); | ||||
| 
 | ||||
|             $this->buildCache(); | ||||
| 
 | ||||
|             if (Ninja::isSelfHost() && $account->set_react_as_default_ap) { | ||||
|                 return response()->view('react.index', $data)->header('X-Frame-Options', 'SAMEORIGIN', false); | ||||
|             } else { | ||||
|  | ||||
| @ -19,7 +19,6 @@ use Illuminate\Http\Request; | ||||
|  */ | ||||
| class BrevoController extends BaseController | ||||
| { | ||||
|     private $invitation; | ||||
| 
 | ||||
|     public function __construct() | ||||
|     { | ||||
|  | ||||
| @ -11,8 +11,9 @@ | ||||
| 
 | ||||
| namespace App\Http\Controllers; | ||||
| 
 | ||||
| use App\Http\Requests\Chart\ShowChartRequest; | ||||
| use App\Services\Chart\ChartService; | ||||
| use App\Http\Requests\Chart\ShowChartRequest; | ||||
| use App\Http\Requests\Chart\ShowCalculatedFieldRequest; | ||||
| 
 | ||||
| class ChartController extends BaseController | ||||
| { | ||||
| @ -65,5 +66,15 @@ class ChartController extends BaseController | ||||
|         return response()->json($cs->chart_summary($request->input('start_date'), $request->input('end_date')), 200); | ||||
|     } | ||||
| 
 | ||||
|     public function calculatedField(ShowCalculatedFieldRequest $request) | ||||
|     { | ||||
| 
 | ||||
|         /** @var \App\Models\User auth()->user() */ | ||||
|         $user = auth()->user(); | ||||
|         $cs = new ChartService($user->company(), $user, $user->isAdmin()); | ||||
|         $result = $cs->getCalculatedField($request->all()); | ||||
|          | ||||
|         return response()->json($result, 200); | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -89,7 +89,7 @@ class ClientController extends BaseController | ||||
|     /** | ||||
|      * | ||||
|      * @param ClientFilters $filters | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function index(ClientFilters $filters) | ||||
| @ -106,7 +106,7 @@ class ClientController extends BaseController | ||||
|      * | ||||
|      * @param ShowClientRequest $request | ||||
|      * @param Client $client | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function show(ShowClientRequest $request, Client $client) | ||||
| @ -119,7 +119,7 @@ class ClientController extends BaseController | ||||
|      * | ||||
|      * @param EditClientRequest $request | ||||
|      * @param Client $client | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function edit(EditClientRequest $request, Client $client) | ||||
| @ -132,7 +132,7 @@ class ClientController extends BaseController | ||||
|      * | ||||
|      * @param UpdateClientRequest $request | ||||
|      * @param Client $client | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function update(UpdateClientRequest $request, Client $client) | ||||
| @ -141,7 +141,7 @@ class ClientController extends BaseController | ||||
|             return $request->disallowUpdate(); | ||||
|         } | ||||
| 
 | ||||
|         /** @var \App\Models\User $user */ | ||||
|         /** @var ?\App\Models\User $user */ | ||||
|         $user = auth()->user(); | ||||
| 
 | ||||
|         $client = $this->client_repo->save($request->all(), $client); | ||||
| @ -157,7 +157,7 @@ class ClientController extends BaseController | ||||
|      * Show the form for creating a new resource. | ||||
|      * | ||||
|      * @param CreateClientRequest $request | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function create(CreateClientRequest $request) | ||||
| @ -174,7 +174,7 @@ class ClientController extends BaseController | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param StoreClientRequest $request | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function store(StoreClientRequest $request) | ||||
| @ -203,7 +203,7 @@ class ClientController extends BaseController | ||||
|      * | ||||
|      * @param DestroyClientRequest $request | ||||
|      * @param Client $client | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      * @throws \Exception | ||||
|      */ | ||||
| @ -217,7 +217,7 @@ class ClientController extends BaseController | ||||
|     /** | ||||
|      * Perform bulk actions on the list view. | ||||
|      * | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function bulk(BulkClientRequest $request) | ||||
| @ -250,22 +250,22 @@ class ClientController extends BaseController | ||||
|             return response()->json(['message' => $hash_or_response], 200); | ||||
|         } | ||||
| 
 | ||||
|         if($action == 'assign_group' && $user->can('edit', $clients->first())){ | ||||
|         if($action == 'assign_group' && $user->can('edit', $clients->first())) { | ||||
| 
 | ||||
|             $this->client_repo->assignGroup($clients, $request->group_settings_id); | ||||
|              | ||||
| 
 | ||||
|             return $this->listResponse(Client::query()->withTrashed()->company()->whereIn('id', $request->ids)); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         if($action == 'bulk_update' && $user->can('edit', $clients->first())){ | ||||
|         if($action == 'bulk_update' && $user->can('edit', $clients->first())) { | ||||
| 
 | ||||
|             $clients = Client::withTrashed() | ||||
|                     ->company() | ||||
|                     ->whereIn('id', $request->ids); | ||||
| 
 | ||||
|             $this->client_repo->bulkUpdate($clients, $request->column, $request->new_value); | ||||
|              | ||||
| 
 | ||||
|             return $this->listResponse(Client::query()->withTrashed()->company()->whereIn('id', $request->ids)); | ||||
| 
 | ||||
|         } | ||||
| @ -284,7 +284,7 @@ class ClientController extends BaseController | ||||
|      * | ||||
|      * @param UploadClientRequest $request | ||||
|      * @param Client $client | ||||
|      * @return Response | ||||
|      * @return Response| \Illuminate\Http\JsonResponse | ||||
|      * | ||||
|      */ | ||||
|     public function upload(UploadClientRequest $request, Client $client) | ||||
| @ -305,7 +305,7 @@ class ClientController extends BaseController | ||||
|      * | ||||
|      * @param PurgeClientRequest $request | ||||
|      * @param Client $client | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|      * | ||||
|      */ | ||||
|     public function purge(PurgeClientRequest $request, Client $client) | ||||
| @ -333,7 +333,7 @@ class ClientController extends BaseController | ||||
|          * @param PurgeClientRequest $request | ||||
|          * @param Client $client | ||||
|          * @param string $mergeable_client | ||||
|          * @return \Illuminate\Http\JsonResponse | ||||
|          * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|          * | ||||
|          */ | ||||
| 
 | ||||
| @ -351,9 +351,10 @@ class ClientController extends BaseController | ||||
|             return response()->json(['message' => "Client not found"], 400); | ||||
|         } | ||||
| 
 | ||||
|         if($m_client->id == $client->id)  | ||||
|         if($m_client->id == $client->id) { | ||||
|             return response()->json(['message' => "Attempting to merge the same client is not possible."], 400); | ||||
|          | ||||
|         } | ||||
| 
 | ||||
|         $merged_client = $client->service()->merge($m_client)->save(); | ||||
| 
 | ||||
|         return $this->itemResponse($merged_client); | ||||
| @ -364,7 +365,7 @@ class ClientController extends BaseController | ||||
|      * | ||||
|      * @param  PurgeClientRequest $request | ||||
|      * @param  Client $client | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|      */ | ||||
|     public function updateTaxData(PurgeClientRequest $request, Client $client) | ||||
|     { | ||||
| @ -380,7 +381,7 @@ class ClientController extends BaseController | ||||
|      * | ||||
|      * @param  ReactivateClientEmailRequest $request | ||||
|      * @param  string $bounce_id //could also be the invitationId
 | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response | ||||
|      */ | ||||
|     public function reactivateEmail(ReactivateClientEmailRequest $request, string $bounce_id) | ||||
|     { | ||||
| @ -425,10 +426,10 @@ class ClientController extends BaseController | ||||
| 
 | ||||
|         try { | ||||
| 
 | ||||
|             /** @var \Postmark\Models\DynamicResponseModel $response */ | ||||
|             /** @var ?\Postmark\Models\DynamicResponseModel $response */ | ||||
|             $response = $postmark->activateBounce((int)$bounce_id); | ||||
| 
 | ||||
|             if($response && $response?->Message == 'OK' && !$response->Bounce->Inactive && $response->Bounce->Email) { | ||||
|             if($response && $response?->Message == 'OK' && !$response->Bounce->Inactive && $response->Bounce->Email) { // @phpstan-ignore-line
 | ||||
| 
 | ||||
|                 $email =  $response->Bounce->Email; | ||||
|                 //remove email from quarantine. //@TODO
 | ||||
|  | ||||
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