diff --git a/app/Exports/Common/Items.php b/app/Exports/Common/Items.php index aaad65306..c2865fc11 100644 --- a/app/Exports/Common/Items.php +++ b/app/Exports/Common/Items.php @@ -4,10 +4,13 @@ namespace App\Exports\Common; use App\Exports\Common\Sheets\Items as Base; use App\Exports\Common\Sheets\ItemTaxes; +use Maatwebsite\Excel\Concerns\Exportable; use Maatwebsite\Excel\Concerns\WithMultipleSheets; class Items implements WithMultipleSheets { + use Exportable; + public $ids; public function __construct($ids = null) diff --git a/app/Exports/Purchases/Bills.php b/app/Exports/Purchases/Bills.php index 6396c969a..32a450235 100644 --- a/app/Exports/Purchases/Bills.php +++ b/app/Exports/Purchases/Bills.php @@ -8,10 +8,13 @@ use App\Exports\Purchases\Sheets\BillItemTaxes; use App\Exports\Purchases\Sheets\BillHistories; use App\Exports\Purchases\Sheets\BillTotals; use App\Exports\Purchases\Sheets\BillTransactions; +use Maatwebsite\Excel\Concerns\Exportable; use Maatwebsite\Excel\Concerns\WithMultipleSheets; class Bills implements WithMultipleSheets { + use Exportable; + public $ids; public function __construct($ids = null) diff --git a/app/Exports/Sales/Invoices.php b/app/Exports/Sales/Invoices.php index 00c8349f4..d6b8e8abc 100644 --- a/app/Exports/Sales/Invoices.php +++ b/app/Exports/Sales/Invoices.php @@ -8,10 +8,13 @@ use App\Exports\Sales\Sheets\InvoiceItemTaxes; use App\Exports\Sales\Sheets\InvoiceHistories; use App\Exports\Sales\Sheets\InvoiceTotals; use App\Exports\Sales\Sheets\InvoiceTransactions; +use Maatwebsite\Excel\Concerns\Exportable; use Maatwebsite\Excel\Concerns\WithMultipleSheets; class Invoices implements WithMultipleSheets { + use Exportable; + public $ids; public function __construct($ids = null) diff --git a/app/Models/Common/Company.php b/app/Models/Common/Company.php index 5b4c94826..02dc23332 100644 --- a/app/Models/Common/Company.php +++ b/app/Models/Common/Company.php @@ -441,9 +441,9 @@ class Company extends Eloquent return $this->getMedia('company_logo')->last(); } - public function makeCurrent() + public function makeCurrent($force = false) { - if ($this->isCurrent()) { + if (!$force && $this->isCurrent()) { return $this; } diff --git a/composer.json b/composer.json index 6fa3ba084..b30c02219 100644 --- a/composer.json +++ b/composer.json @@ -99,6 +99,7 @@ "vendor/akaunting/laravel-module/src/Commands/InstallCommand.php", "vendor/laravel/framework/src/Illuminate/Translation/MessageSelector.php", "vendor/laravel/framework/src/Illuminate/View/Concerns/ManagesStacks.php", + "vendor/maatwebsite/excel/src/Fakes/ExcelFake.php", "vendor/maatwebsite/excel/src/QueuedWriter.php", "vendor/symfony/process/PhpExecutableFinder.php" ], diff --git a/composer.lock b/composer.lock index f9dd6458a..079cb086b 100644 --- a/composer.lock +++ b/composer.lock @@ -8,23 +8,23 @@ "packages": [ { "name": "akaunting/laravel-firewall", - "version": "1.2.13", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/akaunting/laravel-firewall.git", - "reference": "e686eda1826f83dea2b403480274800c67181d4a" + "reference": "5803f8166b98491feafb2367c8232361e800fea9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/akaunting/laravel-firewall/zipball/e686eda1826f83dea2b403480274800c67181d4a", - "reference": "e686eda1826f83dea2b403480274800c67181d4a", + "url": "https://api.github.com/repos/akaunting/laravel-firewall/zipball/5803f8166b98491feafb2367c8232361e800fea9", + "reference": "5803f8166b98491feafb2367c8232361e800fea9", "shasum": "" }, "require": { "guzzlehttp/guzzle": ">=6.0", "jenssegers/agent": "2.6.*", - "laravel/framework": ">=5.4", - "php": ">=5.6.4" + "laravel/framework": ">=5.5", + "php": ">=7.0" }, "require-dev": { "orchestra/testbench": ">=3.4", @@ -69,9 +69,9 @@ ], "support": { "issues": "https://github.com/akaunting/laravel-firewall/issues", - "source": "https://github.com/akaunting/laravel-firewall/tree/1.2.13" + "source": "https://github.com/akaunting/laravel-firewall/tree/1.3.0" }, - "time": "2021-03-12T19:05:08+00:00" + "time": "2021-04-17T08:14:42+00:00" }, { "name": "akaunting/laravel-language", @@ -6818,16 +6818,16 @@ }, { "name": "nunomaduro/larastan", - "version": "v0.7.3", + "version": "v0.7.4", "source": { "type": "git", "url": "https://github.com/nunomaduro/larastan.git", - "reference": "9c515d46851dca5a99fc82c0a69392c362b7affd" + "reference": "0ceef2a39b45be9d7f7dd96192a1721ba5112278" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/larastan/zipball/9c515d46851dca5a99fc82c0a69392c362b7affd", - "reference": "9c515d46851dca5a99fc82c0a69392c362b7affd", + "url": "https://api.github.com/repos/nunomaduro/larastan/zipball/0ceef2a39b45be9d7f7dd96192a1721ba5112278", + "reference": "0ceef2a39b45be9d7f7dd96192a1721ba5112278", "shasum": "" }, "require": { @@ -6891,7 +6891,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/larastan/issues", - "source": "https://github.com/nunomaduro/larastan/tree/v0.7.3" + "source": "https://github.com/nunomaduro/larastan/tree/v0.7.4" }, "funding": [ { @@ -6911,7 +6911,7 @@ "type": "patreon" } ], - "time": "2021-04-12T11:01:46+00:00" + "time": "2021-04-16T08:25:31+00:00" }, { "name": "omnipay/common", diff --git a/database/seeds/TestCompany.php b/database/seeds/TestCompany.php index 426231482..7191464a8 100644 --- a/database/seeds/TestCompany.php +++ b/database/seeds/TestCompany.php @@ -50,13 +50,11 @@ class TestCompany extends Seeder 'schedule.send_invoice_reminder' => '1', 'schedule.send_bill_reminder' => '1', 'wizard.completed' => '1', + 'email.protocol' => 'array', ], ])); - $company->makeCurrent(); - - setting()->set(['email.protocol' => 'array']); - setting()->save(); + $company->makeCurrent(true); $this->command->info('Test company created.'); } diff --git a/overrides/maatwebsite/excel/Fakes/ExcelFake.php b/overrides/maatwebsite/excel/Fakes/ExcelFake.php new file mode 100644 index 000000000..8a6c0a12d --- /dev/null +++ b/overrides/maatwebsite/excel/Fakes/ExcelFake.php @@ -0,0 +1,358 @@ +downloads[$fileName] = $export; + + return new BinaryFileResponse(__DIR__ . '/fake_file'); + } + + /** + * {@inheritdoc} + */ + public function store($export, string $filePath, string $disk = null, string $writerType = null, $diskOptions = []) + { + if ($export instanceof ShouldQueue) { + // @todo removed to fix explicit queue exports + //return $this->queue($export, $filePath, $disk, $writerType); + } + + $this->stored[$disk ?? 'default'][$filePath] = $export; + + return true; + } + + /** + * {@inheritdoc} + */ + public function queue($export, string $filePath, string $disk = null, string $writerType = null, $diskOptions = []) + { + Queue::fake(); + + $this->stored[$disk ?? 'default'][$filePath] = $export; + $this->queued[$disk ?? 'default'][$filePath] = $export; + + $this->job = new class { + use Queueable; + + public function handle() + { + // + } + }; + + Queue::push($this->job); + + return new PendingDispatch($this->job); + } + + /** + * @param object $export + * @param string $writerType + * + * @return string + */ + public function raw($export, string $writerType) + { + return 'RAW-CONTENTS'; + } + + /** + * @param object $import + * @param string|UploadedFile $file + * @param string|null $disk + * @param string|null $readerType + * + * @return Reader|PendingDispatch + */ + public function import($import, $file, string $disk = null, string $readerType = null) + { + if ($import instanceof ShouldQueue) { + // @todo removed to fix explicit queue imports + //return $this->queueImport($import, $file, $disk, $readerType); + } + + $filePath = ($file instanceof UploadedFile) ? $file->getClientOriginalName() : $file; + + $this->imported[$disk ?? 'default'][$filePath] = $import; + + return $this; + } + + /** + * @param object $import + * @param string|UploadedFile $file + * @param string|null $disk + * @param string|null $readerType + * + * @return array + */ + public function toArray($import, $file, string $disk = null, string $readerType = null): array + { + $filePath = ($file instanceof UploadedFile) ? $file->getFilename() : $file; + + $this->imported[$disk ?? 'default'][$filePath] = $import; + + return []; + } + + /** + * @param object $import + * @param string|UploadedFile $file + * @param string|null $disk + * @param string|null $readerType + * + * @return Collection + */ + public function toCollection($import, $file, string $disk = null, string $readerType = null): Collection + { + $filePath = ($file instanceof UploadedFile) ? $file->getFilename() : $file; + + $this->imported[$disk ?? 'default'][$filePath] = $import; + + return new Collection(); + } + + /** + * @param ShouldQueue $import + * @param string|UploadedFile $file + * @param string|null $disk + * @param string $readerType + * + * @return PendingDispatch + */ + public function queueImport(ShouldQueue $import, $file, string $disk = null, string $readerType = null) + { + Queue::fake(); + + $filePath = ($file instanceof UploadedFile) ? $file->getFilename() : $file; + + $this->queued[$disk ?? 'default'][$filePath] = $import; + $this->imported[$disk ?? 'default'][$filePath] = $import; + + return new PendingDispatch(new class { + use Queueable; + + public function handle() + { + // + } + }); + } + + /** + * When asserting downloaded, stored, queued or imported, use regular expression + * to look for a matching file path. + * + * @return void + */ + public function matchByRegex() + { + $this->matchByRegex = true; + } + + /** + * When asserting downloaded, stored, queued or imported, use regular string + * comparison for matching file path. + * + * @return void + */ + public function doNotMatchByRegex() + { + $this->matchByRegex = false; + } + + /** + * @param string $fileName + * @param callable|null $callback + */ + public function assertDownloaded(string $fileName, $callback = null) + { + $fileName = $this->assertArrayHasKey($fileName, $this->downloads, sprintf('%s is not downloaded', $fileName)); + + $callback = $callback ?: function () { + return true; + }; + + Assert::assertTrue( + $callback($this->downloads[$fileName]), + "The file [{$fileName}] was not downloaded with the expected data." + ); + } + + /** + * @param string $filePath + * @param string|callable|null $disk + * @param callable|null $callback + */ + public function assertStored(string $filePath, $disk = null, $callback = null) + { + if (is_callable($disk)) { + $callback = $disk; + $disk = null; + } + + $disk = $disk ?? 'default'; + $storedOnDisk = $this->stored[$disk] ?? []; + + $filePath = $this->assertArrayHasKey( + $filePath, + $storedOnDisk, + sprintf('%s is not stored on disk %s', $filePath, $disk) + ); + + $callback = $callback ?: function () { + return true; + }; + + Assert::assertTrue( + $callback($storedOnDisk[$filePath]), + "The file [{$filePath}] was not stored with the expected data." + ); + } + + /** + * @param string $filePath + * @param string|callable|null $disk + * @param callable|null $callback + */ + public function assertQueued(string $filePath, $disk = null, $callback = null) + { + if (is_callable($disk)) { + $callback = $disk; + $disk = null; + } + + $disk = $disk ?? 'default'; + $queuedForDisk = $this->queued[$disk] ?? []; + + $filePath = $this->assertArrayHasKey( + $filePath, + $queuedForDisk, + sprintf('%s is not queued for export on disk %s', $filePath, $disk) + ); + + $callback = $callback ?: function () { + return true; + }; + + Assert::assertTrue( + $callback($queuedForDisk[$filePath]), + "The file [{$filePath}] was not stored with the expected data." + ); + } + + public function assertQueuedWithChain($chain): void + { + Queue::assertPushedWithChain(get_class($this->job), $chain); + } + + /** + * @param string $filePath + * @param string|callable|null $disk + * @param callable|null $callback + */ + public function assertImported(string $filePath, $disk = null, $callback = null) + { + if (is_callable($disk)) { + $callback = $disk; + $disk = null; + } + + $disk = $disk ?? 'default'; + $importedOnDisk = $this->imported[$disk] ?? []; + + $filePath = $this->assertArrayHasKey( + $filePath, + $importedOnDisk, + sprintf('%s is not stored on disk %s', $filePath, $disk) + ); + + $callback = $callback ?: function () { + return true; + }; + + Assert::assertTrue( + $callback($importedOnDisk[$filePath]), + "The file [{$filePath}] was not imported with the expected data." + ); + } + + /** + * Asserts that an array has a specified key and returns the key if successful. + * @see matchByRegex for more information about file path matching + * + * @param string $key + * @param array $array + * @param string $message + * + * @return string + * + * @throws ExpectationFailedException + * @throws \SebastianBergmann\RecursionContext\InvalidArgumentException + * @throws Exception + */ + protected function assertArrayHasKey(string $key, array $disk, string $message = ''): string + { + if ($this->matchByRegex) { + $files = array_keys($disk); + $results = preg_grep($key, $files); + Assert::assertGreaterThan(0, count($results), $message); + Assert::assertEquals(1, count($results), "More than one result matches the file name expression '$key'."); + + return $results[0]; + } + Assert::assertArrayHasKey($key, $disk, $message); + + return $key; + } +}