diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index fb7cde006ec1..479e647a7f32 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -535,7 +535,7 @@ class InvoiceController extends BaseController if (Ninja::isHosted() && (stripos($action, 'email') !== false) && !auth()->user()->company()->account->account_sms_verified) { return response(['message' => 'Please verify your account to send emails.'], 400); } - + $invoices = Invoice::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get(); if (! $invoices) { @@ -678,7 +678,7 @@ class InvoiceController extends BaseController case 'clone_to_invoice': $invoice = CloneInvoiceFactory::create($invoice, auth()->user()->id); return $this->itemResponse($invoice); - + case 'clone_to_quote': $quote = CloneInvoiceToQuoteFactory::create($invoice, auth()->user()->id); @@ -860,6 +860,73 @@ class InvoiceController extends BaseController }, basename($file), $headers); } + /** + * @OA\Get( + * path="/api/v1/invoice/{invitation_key}/download_xinvoice", + * operationId="downloadXInvoice", + * tags={"invoices"}, + * summary="Download a specific x-invoice by invitation key", + * description="Downloads a specific x-invoice", + * @OA\Parameter(ref="#/components/parameters/X-API-TOKEN"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter(ref="#/components/parameters/include"), + * @OA\Parameter( + * name="invitation_key", + * in="path", + * description="The Invoice Invitation Key", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Returns the x-invoice pdf", + * @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + * + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + * @param $invitation_key + * @return \Symfony\Component\HttpFoundation\BinaryFileResponse + */ + public function downloadXInvoice($invitation_key) + { + $invitation = $this->invoice_repo->getInvitationByKey($invitation_key); + + if (! $invitation) { + return response()->json(['message' => 'no record found'], 400); + } + + $contact = $invitation->contact; + $invoice = $invitation->invoice; + + $file = $invoice->service()->getXInvoice($contact); + + $headers = ['Content-Type' => 'application/xml']; + + if (request()->input('inline') == 'true') { + $headers = array_merge($headers, ['Content-Disposition' => 'inline']); + } + + return response()->streamDownload(function () use ($file) { + echo Storage::get($file); + }, basename($file), $headers); + } + /** * @OA\Get( * path="/api/v1/invoices/{id}/delivery_note", diff --git a/app/Jobs/Invoice/CreateXInvoice.php b/app/Jobs/Invoice/CreateXInvoice.php index d0d61fe5cd41..ee802533a337 100644 --- a/app/Jobs/Invoice/CreateXInvoice.php +++ b/app/Jobs/Invoice/CreateXInvoice.php @@ -12,7 +12,6 @@ use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Storage; -use function Symfony\Component\String\b; class CreateXInvoice implements ShouldQueue diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index 68cb3101ef32..e37e5597bb64 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -187,7 +187,7 @@ class InvoiceService public function getXInvoice($contact = null) { - return (new GetInvoiceXInvoice($this->invoice))->run(); + return (new GetInvoiceXInvoice($this->invoice, $contact))->run(); } public function sendEmail($contact = null) @@ -448,7 +448,7 @@ class InvoiceService if ($force) { $this->invoice->invitations->each(function ($invitation) { (new CreateEntityPdf($invitation))->handle(); - // Add XInvoice + (new CreateXInvoice($invitation))->handle(); }); return $this; @@ -456,7 +456,7 @@ class InvoiceService $this->invoice->invitations->each(function ($invitation) { CreateEntityPdf::dispatch($invitation); - // Add XInvoice + CreateXInvoice::dispatch($invitation); }); } catch (\Exception $e) { nlog('failed creating invoices in Touch PDF'); diff --git a/routes/api.php b/routes/api.php index daf2db3a84a1..4dd7b33e6e30 100644 --- a/routes/api.php +++ b/routes/api.php @@ -206,6 +206,7 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale'] Route::get('invoices/{invoice}/{action}', [InvoiceController::class, 'action'])->name('invoices.action'); Route::put('invoices/{invoice}/upload', [InvoiceController::class, 'upload'])->name('invoices.upload'); Route::get('invoice/{invitation_key}/download', [InvoiceController::class, 'downloadPdf'])->name('invoices.downloadPdf'); + Route::get('invoice/{invitation_key}/download_xinvoice', [InvoiceController::class, 'downloadXInvoice_pdf'])->name('invoices.downloadXInvoice'); Route::post('invoices/bulk', [InvoiceController::class, 'bulk'])->name('invoices.bulk'); Route::post('invoices/update_reminders', [InvoiceController::class, 'update_reminders'])->name('invoices.update_reminders'); @@ -317,7 +318,7 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale'] Route::post('verify', [TwilioController::class, 'generate'])->name('verify.generate')->middleware('throttle:100,1'); Route::post('verify/confirm', [TwilioController::class, 'confirm'])->name('verify.confirm'); - + Route::resource('vendors', VendorController::class); // name = (vendors. index / create / show / update / destroy / edit Route::post('vendors/bulk', [VendorController::class, 'bulk'])->name('vendors.bulk'); Route::put('vendors/{vendor}/upload', [VendorController::class, 'upload']);