From 8ffbb54e3be46e87cad90fee3fe04612bbaab89f Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 22 Jan 2025 17:22:31 +1100 Subject: [PATCH] Updates for NordigenController --- .../Controllers/Bank/NordigenController.php | 5 +- app/Http/Controllers/InvoiceController.php | 50 ++++++++--- app/Http/Controllers/PreviewController.php | 2 +- .../PreviewPurchaseOrderController.php | 2 +- app/Jobs/Entity/CreateBatchablePdf.php | 51 ++++++++++++ app/Jobs/Invoice/PrintInvoiceBatch.php | 82 +++++++++++++++++++ config/queue.php | 4 + ...add_verification_setting_to_gocardless.php | 13 ++- 8 files changed, 189 insertions(+), 20 deletions(-) create mode 100644 app/Jobs/Entity/CreateBatchablePdf.php create mode 100644 app/Jobs/Invoice/PrintInvoiceBatch.php diff --git a/app/Http/Controllers/Bank/NordigenController.php b/app/Http/Controllers/Bank/NordigenController.php index bfbb6a4d68..e823c26961 100644 --- a/app/Http/Controllers/Bank/NordigenController.php +++ b/app/Http/Controllers/Bank/NordigenController.php @@ -165,6 +165,7 @@ class NordigenController extends BaseController return $this->failed('requisition-no-accounts', $context, $company); } + // connect new accounts $bank_integration_ids = []; foreach ($requisition['accounts'] as $nordigenAccountId) { @@ -213,10 +214,6 @@ class NordigenController extends BaseController } } - - if(!$bank_integration) - continue; - // perform update in background $company->account->bank_integrations ->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN) diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index f33d751508..80a325a59e 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -544,13 +544,44 @@ class InvoiceController extends BaseController } if ($action == 'bulk_print' && $user->can('view', $invoices->first())) { - $paths = $invoices->map(function ($invoice) { - return (new \App\Jobs\Entity\CreateRawPdf($invoice->invitations->first()))->handle(); - }); + $start = microtime(true); + + // 2025-01-22 Legacy implementation of bulk print + // $paths = $invoices->map(function ($invoice) { + // return (new \App\Jobs\Entity\CreateRawPdf($invoice->invitations->first()))->handle(); + // }); - return response()->streamDownload(function () use ($paths) { - echo $merge = (new PdfMerge($paths->toArray()))->run(); - }, 'print.pdf', ['Content-Type' => 'application/pdf']); + // return response()->streamDownload(function () use ($paths) { + // echo $merge = (new PdfMerge($paths->toArray()))->run(); + // }, 'print.pdf', ['Content-Type' => 'application/pdf']); + + $batch_id = (new \App\Jobs\Invoice\PrintInvoiceBatch($invoices->pluck('id')->toArray(), $user->company()->db))->handle(); + $batch = \Illuminate\Support\Facades\Bus::findBatch($batch_id); + $batch_key = $batch->name; + + $finished = false; + + do{ + usleep(500000); + $batch = \Illuminate\Support\Facades\Bus::findBatch($batch_id); + $finished = $batch->finished(); + }while(!$finished); + + $paths = $invoices->map(function ($invoice) use($batch_key){ + return \Illuminate\Support\Facades\Cache::pull("{$batch_key}-{$invoice->id}"); + })->filter(function ($value) { + return !is_null($value); + })->toArray(); + + $mergedPdf = (new PdfMerge($paths))->run(); + + return response()->streamDownload(function () use ($mergedPdf) { + echo $mergedPdf; + }, 'print.pdf', [ + 'Content-Type' => 'application/pdf', + 'Cache-Control:' => 'no-cache', + 'Server-Timing' => (string)(microtime(true) - $start) + ]); } if ($action == 'template' && $user->can('view', $invoices->first())) { @@ -592,13 +623,6 @@ class InvoiceController extends BaseController $invoice->service()->sendEmail(email_type: $request->input('email_type', $invoice->calculateTemplate('invoice'))); }); - // if ($user->can('edit', $invoice)) { - - // $template = $request->input('email_type', $invoice->calculateTemplate('invoice')); - - // BulkInvoiceJob::dispatch($invoices->pluck('id')->toArray(), $user->company()->db, $template); - // } - return $this->listResponse(Invoice::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()); } diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index 47250a84df..7e39fd4d34 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -100,7 +100,7 @@ class PreviewController extends BaseController 'Content-Disposition' => 'inline', 'Content-Type' => 'application/pdf', 'Cache-Control:' => 'no-cache', - 'Server-Timing' => microtime(true) - $start + 'Server-Timing' => (string)(microtime(true) - $start) ]); } diff --git a/app/Http/Controllers/PreviewPurchaseOrderController.php b/app/Http/Controllers/PreviewPurchaseOrderController.php index 922025c88e..86f218292e 100644 --- a/app/Http/Controllers/PreviewPurchaseOrderController.php +++ b/app/Http/Controllers/PreviewPurchaseOrderController.php @@ -215,7 +215,7 @@ class PreviewPurchaseOrderController extends BaseController 'Content-Disposition' => 'inline', 'Content-Type' => 'application/pdf', 'Cache-Control:' => 'no-cache', - 'Server-Timing' => microtime(true) - $start + 'Server-Timing' => (string)(microtime(true) - $start) ]); diff --git a/app/Jobs/Entity/CreateBatchablePdf.php b/app/Jobs/Entity/CreateBatchablePdf.php new file mode 100644 index 0000000000..1c26861c35 --- /dev/null +++ b/app/Jobs/Entity/CreateBatchablePdf.php @@ -0,0 +1,51 @@ +invitation = $invitation; + $this->batch_key = $batch_key; + } + + public function handle() + { + $pdf = (new CreateRawPdf($this->invitation))->handle(); + + Cache::put($this->batch_key, $pdf); + } + + public function failed($e) + { + nlog("CreateBatchablePdf failed: {$e->getMessage()}"); + } +} diff --git a/app/Jobs/Invoice/PrintInvoiceBatch.php b/app/Jobs/Invoice/PrintInvoiceBatch.php new file mode 100644 index 0000000000..d78c1325e5 --- /dev/null +++ b/app/Jobs/Invoice/PrintInvoiceBatch.php @@ -0,0 +1,82 @@ +db); + + $batch_key = Str::uuid(); + + $invites = Invoice::with('invitations')->withTrashed() + ->whereIn('id', $this->invoice_ids) + ->get() + ->map(function ($invoice) use ($batch_key){ + return new CreateBatchablePdf($invoice->invitations->first(), "{$batch_key}-{$invoice->id}"); + })->toArray(); + + $mergedPdf = null; + + $batch = Bus::batch($invites) + ->before(function (Batch $batch) { + // The batch has been created but no jobs have been added... + // nlog("before"); + })->progress(function (Batch $batch) { + // A single job has completed successfully... + // nlog("Batch {$batch->id} is {$batch->progress()}% complete"); + })->then(function (Batch $batch) { + // All jobs completed successfully... + // nlog("job finished"); + + })->catch(function (Batch $batch, Throwable $e) { + // First batch job failure detected... + // nlog("PrintInvoiceBatch failed: {$e->getMessage()}"); + })->finally(function (Batch $batch) { + // The batch has finished executing... + // nlog("I have finished"); + })->name($batch_key)->dispatch(); + + return $batch->id; + + } +} diff --git a/config/queue.php b/config/queue.php index 4122822991..36e6d9002c 100644 --- a/config/queue.php +++ b/config/queue.php @@ -73,6 +73,10 @@ return [ ], + 'batching' => [ + 'database' => env('DB_BATCH', 'mysql'), + 'table' => 'job_batches', + ], /* |-------------------------------------------------------------------------- | Failed Queue Jobs diff --git a/database/migrations/2025_01_22_013047_2025_01_22_add_verification_setting_to_gocardless.php b/database/migrations/2025_01_22_013047_2025_01_22_add_verification_setting_to_gocardless.php index 154f8a2608..db97b9da61 100644 --- a/database/migrations/2025_01_22_013047_2025_01_22_add_verification_setting_to_gocardless.php +++ b/database/migrations/2025_01_22_013047_2025_01_22_add_verification_setting_to_gocardless.php @@ -12,7 +12,18 @@ return new class extends Migration public function up(): void { - // "verifyBankAccount":false, + Schema::create('job_batches', function (Blueprint $table) { + $table->string('id')->primary(); + $table->string('name'); + $table->integer('total_jobs'); + $table->integer('pending_jobs'); + $table->integer('failed_jobs'); + $table->longText('failed_job_ids'); + $table->mediumText('options')->nullable(); + $table->integer('cancelled_at')->nullable(); + $table->integer('created_at'); + $table->integer('finished_at')->nullable(); + }); \App\Models\CompanyGateway::withTrashed()->where('gateway_key','b9886f9257f0c6ee7c302f1c74475f6c') ->cursor()