mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-03 03:54:34 -04:00
Migration improvements: (#3428)
- Refactored exceptions - Changed failed.blade.php - Removed report() method from exceptions - Added new force flag for MigrationController.php
This commit is contained in:
parent
20c818cf97
commit
280271718b
@ -7,13 +7,5 @@ use Throwable;
|
|||||||
|
|
||||||
class MigrationValidatorFailed extends Exception
|
class MigrationValidatorFailed extends Exception
|
||||||
{
|
{
|
||||||
public function __construct($message = "", $code = 0, Throwable $previous = null)
|
// ..
|
||||||
{
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function report()
|
|
||||||
{
|
|
||||||
return $this->message;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,5 @@ use Throwable;
|
|||||||
|
|
||||||
class NonExistingMigrationFile extends Exception
|
class NonExistingMigrationFile extends Exception
|
||||||
{
|
{
|
||||||
public function __construct($message = "", $code = 0, Throwable $previous = null)
|
// ..
|
||||||
{
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function report()
|
|
||||||
{
|
|
||||||
return 'Migration file doesn\'t exist or it is corrupted.';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,22 +7,5 @@ use Throwable;
|
|||||||
|
|
||||||
class ProcessingMigrationArchiveFailed extends Exception
|
class ProcessingMigrationArchiveFailed extends Exception
|
||||||
{
|
{
|
||||||
/**
|
// ..
|
||||||
* @var Throwable
|
|
||||||
*/
|
|
||||||
private $previous;
|
|
||||||
|
|
||||||
public function __construct($message = "", $code = 0, Throwable $previous = null)
|
|
||||||
{
|
|
||||||
parent::__construct($message, $code, $previous);
|
|
||||||
$this->message = $message;
|
|
||||||
$this->code = $code;
|
|
||||||
$this->previous = $previous;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function report()
|
|
||||||
{
|
|
||||||
return 'Unable to open migration archive.';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,18 +7,5 @@ use Throwable;
|
|||||||
|
|
||||||
class ResourceDependencyMissing extends Exception
|
class ResourceDependencyMissing extends Exception
|
||||||
{
|
{
|
||||||
private $resource;
|
// ..
|
||||||
private $dependency;
|
|
||||||
|
|
||||||
public function __construct($resource, $dependency)
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
$this->resource = $resource;
|
|
||||||
$this->dependency = $dependency;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function report()
|
|
||||||
{
|
|
||||||
return "Resource '{$this->resource}' depends on '{$this->dependency}'.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,5 @@ use Throwable;
|
|||||||
|
|
||||||
class ResourceNotAvailableForMigration extends Exception
|
class ResourceNotAvailableForMigration extends Exception
|
||||||
{
|
{
|
||||||
private $resource;
|
// ..
|
||||||
|
|
||||||
public function __construct($resource)
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
|
|
||||||
$this->resource = $resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function report()
|
|
||||||
{
|
|
||||||
// TODO: Handle this nicely, throw response, etc.
|
|
||||||
return "Resource {$this->resource} is not available for the migration.";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ use App\Exceptions\MigrationValidatorFailed;
|
|||||||
use App\Exceptions\NonExistingMigrationFile;
|
use App\Exceptions\NonExistingMigrationFile;
|
||||||
use App\Exceptions\ProcessingMigrationArchiveFailed;
|
use App\Exceptions\ProcessingMigrationArchiveFailed;
|
||||||
use App\Exceptions\ResourceNotAvailableForMigration;
|
use App\Exceptions\ResourceNotAvailableForMigration;
|
||||||
|
use App\Factory\CompanyFactory;
|
||||||
use App\Http\Requests\Account\CreateAccountRequest;
|
use App\Http\Requests\Account\CreateAccountRequest;
|
||||||
use App\Http\Requests\Migration\UploadMigrationFileRequest;
|
use App\Http\Requests\Migration\UploadMigrationFileRequest;
|
||||||
use App\Jobs\Account\CreateAccount;
|
use App\Jobs\Account\CreateAccount;
|
||||||
@ -192,7 +193,7 @@ class MigrationController extends BaseController
|
|||||||
*/
|
*/
|
||||||
public function startMigration(Request $request, Company $company)
|
public function startMigration(Request $request, Company $company)
|
||||||
{
|
{
|
||||||
if ($request->has('force'))
|
if ($request->has('force') && !empty($request->force))
|
||||||
$this->purgeCompany($company);
|
$this->purgeCompany($company);
|
||||||
|
|
||||||
$migration_file = $request->file('migration')
|
$migration_file = $request->file('migration')
|
||||||
@ -201,12 +202,11 @@ class MigrationController extends BaseController
|
|||||||
if (app()->environment() == 'testing') return;
|
if (app()->environment() == 'testing') return;
|
||||||
|
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$company = $company;
|
|
||||||
|
|
||||||
StartMigration::dispatch($migration_file, $user, $company);
|
StartMigration::dispatch($migration_file, $user, $company);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'_id' => Str::uuid(),
|
'_id' => Str::uuid(),
|
||||||
'method' => config('queue.default'),
|
'method' => config('queue.default'),
|
||||||
'started_at' => now(),
|
'started_at' => now(),
|
||||||
], 200);
|
], 200);
|
||||||
|
@ -131,14 +131,19 @@ class Import implements ShouldQueue
|
|||||||
foreach ($this->data as $key => $resource) {
|
foreach ($this->data as $key => $resource) {
|
||||||
|
|
||||||
if (!in_array($key, $this->available_imports)) {
|
if (!in_array($key, $this->available_imports)) {
|
||||||
throw new ResourceNotAvailableForMigration($key);
|
throw new ResourceNotAvailableForMigration("Resource {$key} is not available for migration.");
|
||||||
}
|
}
|
||||||
\Log::error($key);
|
|
||||||
|
\Log::error($key);
|
||||||
|
|
||||||
$method = sprintf("process%s", Str::ucfirst(Str::camel($key)));
|
$method = sprintf("process%s", Str::ucfirst(Str::camel($key)));
|
||||||
|
|
||||||
$this->{$method}($resource);
|
$this->{$method}($resource);
|
||||||
|
|
||||||
|
info("$key done!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info('Completed🚀🚀🚀🚀🚀 at ' . now());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,7 +160,7 @@ class Import implements ShouldQueue
|
|||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
// \Log::error($validator->errors());
|
// \Log::error($validator->errors());
|
||||||
throw new MigrationValidatorFailed($validator->errors());
|
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($data['account_id']))
|
if (isset($data['account_id']))
|
||||||
@ -185,7 +190,7 @@ class Import implements ShouldQueue
|
|||||||
$validator = Validator::make($data, $rules);
|
$validator = Validator::make($data, $rules);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
throw new MigrationValidatorFailed($validator->errors());
|
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($data as $resource) {
|
foreach ($data as $resource) {
|
||||||
@ -231,7 +236,7 @@ class Import implements ShouldQueue
|
|||||||
$validator = Validator::make($data, $rules);
|
$validator = Validator::make($data, $rules);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
throw new MigrationValidatorFailed($validator->errors());
|
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_repository = new UserRepository();
|
$user_repository = new UserRepository();
|
||||||
@ -324,7 +329,7 @@ class Import implements ShouldQueue
|
|||||||
$validator = Validator::make($data, $rules);
|
$validator = Validator::make($data, $rules);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
throw new MigrationValidatorFailed($validator->errors());
|
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$product_repository = new ProductRepository();
|
$product_repository = new ProductRepository();
|
||||||
@ -358,7 +363,7 @@ class Import implements ShouldQueue
|
|||||||
$validator = Validator::make($data, $rules);
|
$validator = Validator::make($data, $rules);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
throw new MigrationValidatorFailed($validator->errors());
|
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$invoice_repository = new InvoiceRepository();
|
$invoice_repository = new InvoiceRepository();
|
||||||
@ -368,7 +373,7 @@ class Import implements ShouldQueue
|
|||||||
$modified = $resource;
|
$modified = $resource;
|
||||||
|
|
||||||
if (array_key_exists('client_id', $resource) && !array_key_exists('clients', $this->ids)) {
|
if (array_key_exists('client_id', $resource) && !array_key_exists('clients', $this->ids)) {
|
||||||
throw new ResourceDependencyMissing(array_key_first($data), 'clients');
|
throw new ResourceDependencyMissing('Processing invoices failed, because of missing dependency - clients.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
||||||
@ -405,7 +410,7 @@ class Import implements ShouldQueue
|
|||||||
$validator = Validator::make($data, $rules);
|
$validator = Validator::make($data, $rules);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
throw new MigrationValidatorFailed($validator->errors());
|
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$credit_repository = new CreditRepository();
|
$credit_repository = new CreditRepository();
|
||||||
@ -415,7 +420,7 @@ class Import implements ShouldQueue
|
|||||||
$modified = $resource;
|
$modified = $resource;
|
||||||
|
|
||||||
if (array_key_exists('client_id', $resource) && !array_key_exists('clients', $this->ids)) {
|
if (array_key_exists('client_id', $resource) && !array_key_exists('clients', $this->ids)) {
|
||||||
throw new ResourceDependencyMissing(array_key_first($data), 'clients');
|
throw new ResourceDependencyMissing('Processing credits failed, because of missing dependency - clients.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
||||||
@ -451,7 +456,7 @@ class Import implements ShouldQueue
|
|||||||
$validator = Validator::make($data, $rules);
|
$validator = Validator::make($data, $rules);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
throw new MigrationValidatorFailed($validator->errors());
|
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$quote_repository = new QuoteRepository();
|
$quote_repository = new QuoteRepository();
|
||||||
@ -461,7 +466,7 @@ class Import implements ShouldQueue
|
|||||||
$modified = $resource;
|
$modified = $resource;
|
||||||
|
|
||||||
if (array_key_exists('client_id', $resource) && !array_key_exists('clients', $this->ids)) {
|
if (array_key_exists('client_id', $resource) && !array_key_exists('clients', $this->ids)) {
|
||||||
throw new ResourceDependencyMissing(array_key_first($data), 'clients');
|
throw new ResourceDependencyMissing('Processing quotes failed, because of missing dependency - clients.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
||||||
@ -502,7 +507,7 @@ class Import implements ShouldQueue
|
|||||||
$validator = Validator::make($data, $rules);
|
$validator = Validator::make($data, $rules);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
throw new MigrationValidatorFailed($validator->errors());
|
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$payment_repository = new PaymentRepository(new CreditRepository());
|
$payment_repository = new PaymentRepository(new CreditRepository());
|
||||||
@ -512,7 +517,7 @@ class Import implements ShouldQueue
|
|||||||
$modified = $resource;
|
$modified = $resource;
|
||||||
|
|
||||||
if (array_key_exists('client_id', $resource) && !array_key_exists('clients', $this->ids)) {
|
if (array_key_exists('client_id', $resource) && !array_key_exists('clients', $this->ids)) {
|
||||||
throw new ResourceDependencyMissing(array_key_first($data), 'clients');
|
throw new ResourceDependencyMissing('Processing payments failed, because of missing dependency - clients.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
$modified['client_id'] = $this->transformId('clients', $resource['client_id']);
|
||||||
@ -557,11 +562,11 @@ class Import implements ShouldQueue
|
|||||||
$modified = $resource;
|
$modified = $resource;
|
||||||
|
|
||||||
if (array_key_exists('invoice_id', $resource) && $resource['invoice_id'] && !array_key_exists('invoices', $this->ids)) {
|
if (array_key_exists('invoice_id', $resource) && $resource['invoice_id'] && !array_key_exists('invoices', $this->ids)) {
|
||||||
throw new ResourceDependencyMissing(array_key_first($data), 'invoices');
|
throw new ResourceDependencyMissing('Processing documents failed, because of missing dependency - invoices.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists('expense_id', $resource) && $resource['expense_id'] && !array_key_exists('expenses', $this->ids)) {
|
if (array_key_exists('expense_id', $resource) && $resource['expense_id'] && !array_key_exists('expenses', $this->ids)) {
|
||||||
throw new ResourceDependencyMissing(array_key_first($data), 'expenses');
|
throw new ResourceDependencyMissing('Processing documents failed, because of missing dependency - expenses.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Remove because of polymorphic joins. */
|
/** Remove because of polymorphic joins. */
|
||||||
@ -611,7 +616,7 @@ class Import implements ShouldQueue
|
|||||||
$validator = Validator::make($data, $rules);
|
$validator = Validator::make($data, $rules);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
throw new MigrationValidatorFailed($validator->errors());
|
throw new MigrationValidatorFailed(json_encode($validator->errors()));
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($data as $resource) {
|
foreach ($data as $resource) {
|
||||||
|
@ -63,7 +63,7 @@ class StartMigration implements ShouldQueue
|
|||||||
auth()->login($this->user, false);
|
auth()->login($this->user, false);
|
||||||
|
|
||||||
auth()->user()->setCompany($this->company);
|
auth()->user()->setCompany($this->company);
|
||||||
|
|
||||||
$zip = new \ZipArchive();
|
$zip = new \ZipArchive();
|
||||||
$archive = $zip->open($this->filepath);
|
$archive = $zip->open($this->filepath);
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ class StartMigration implements ShouldQueue
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (!$archive)
|
if (!$archive)
|
||||||
throw new ProcessingMigrationArchiveFailed();
|
throw new ProcessingMigrationArchiveFailed('Processing migration archive failed. Migration file is possibly corrupted.');
|
||||||
|
|
||||||
$zip->extractTo(storage_path("migrations/{$filename}"));
|
$zip->extractTo(storage_path("migrations/{$filename}"));
|
||||||
$zip->close();
|
$zip->close();
|
||||||
@ -81,10 +81,9 @@ class StartMigration implements ShouldQueue
|
|||||||
|
|
||||||
$this->start($filename);
|
$this->start($filename);
|
||||||
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing $e) {
|
} catch (NonExistingMigrationFile | ProcessingMigrationArchiveFailed | ResourceNotAvailableForMigration | MigrationValidatorFailed | ResourceDependencyMissing $e) {
|
||||||
Mail::to($this->user)
|
Mail::to($this->user)->send(new MigrationFailed($e, $e->getMessage()));
|
||||||
->send(new MigrationFailed($e, $e->getMessage()));
|
|
||||||
|
if (app()->environment() !== 'production') info($e->getMessage());
|
||||||
if(app()->environment() !== 'production') info($e->getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +97,7 @@ class StartMigration implements ShouldQueue
|
|||||||
$file = storage_path("migrations/$filename/migration.json");
|
$file = storage_path("migrations/$filename/migration.json");
|
||||||
|
|
||||||
if (!file_exists($file))
|
if (!file_exists($file))
|
||||||
throw new NonExistingMigrationFile();
|
throw new NonExistingMigrationFile('Migration file does not exist, or it is corrupted.');
|
||||||
|
|
||||||
$handle = fopen($file, "r");
|
$handle = fopen($file, "r");
|
||||||
$file = fread($handle, filesize($file));
|
$file = fread($handle, filesize($file));
|
||||||
|
@ -11,18 +11,17 @@ class MigrationFailed extends Mailable
|
|||||||
use Queueable, SerializesModels;
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
public $exception;
|
public $exception;
|
||||||
public $message;
|
public $content;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new message instance.
|
* Create a new message instance.
|
||||||
*
|
*
|
||||||
* @param $message
|
* @param $content
|
||||||
* @param $exception
|
* @param $exception
|
||||||
*/
|
*/
|
||||||
public function __construct($exception, $message = null)
|
public function __construct($exception, $content = null)
|
||||||
{
|
{
|
||||||
$this->exception = $exception;
|
$this->exception = $exception;
|
||||||
$this->message = 'Oops, looks like something went wrong with your migration. Please try again, later.';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
36
database/migrations/2020_03_05_123315_create_jobs_table.php
Normal file
36
database/migrations/2020_03_05_123315_create_jobs_table.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateJobsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('jobs', function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id');
|
||||||
|
$table->string('queue')->index();
|
||||||
|
$table->longText('payload');
|
||||||
|
$table->unsignedTinyInteger('attempts');
|
||||||
|
$table->unsignedInteger('reserved_at')->nullable();
|
||||||
|
$table->unsignedInteger('available_at');
|
||||||
|
$table->unsignedInteger('created_at');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('jobs');
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,6 @@ Whoops!
|
|||||||
Looks like your migration failed.
|
Looks like your migration failed.
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
{!! $exception->report() !!}
|
{!! $exception->getMessage() !!}
|
||||||
{!! $message !!}
|
{!! $content !!}
|
||||||
</pre>
|
</pre>
|
||||||
|
@ -504,4 +504,21 @@ class ImportTest extends TestCase
|
|||||||
|
|
||||||
$this->assertTrue(true, 'Documents importing not completed yet. Missing expenses.');
|
$this->assertTrue(true, 'Documents importing not completed yet. Missing expenses.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testExceptionMailSending()
|
||||||
|
{
|
||||||
|
Mail::fake();
|
||||||
|
|
||||||
|
$data['panda_bears'] = [
|
||||||
|
'name' => 'Awesome Panda Bear',
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
Import::dispatchNow($data, $this->company, $this->user);
|
||||||
|
}
|
||||||
|
catch (ResourceNotAvailableForMigration $e) {
|
||||||
|
Mail::to($this->user)->send(new MigrationFailed($e, $e->getMessage()));
|
||||||
|
$this->assertTrue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user