diff --git a/app/Factory/CloneQuoteToInvoiceFactory.php b/app/Factory/CloneQuoteToInvoiceFactory.php index f9866c7597df..13ad94391b14 100644 --- a/app/Factory/CloneQuoteToInvoiceFactory.php +++ b/app/Factory/CloneQuoteToInvoiceFactory.php @@ -28,6 +28,10 @@ class CloneQuoteToInvoiceFactory unset($quote_array['invoice_id']); unset($quote_array['id']); unset($quote_array['invitations']); + unset($quote_array['terms']); + unset($quote_array['public_notes']); + unset($quote_array['footer']); + unset($quote_array['design_id']); foreach ($quote_array as $key => $value) { $invoice->{$key} = $value; diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php index 3d4b56c0988b..9b1bf584d66c 100644 --- a/app/Http/Controllers/ActivityController.php +++ b/app/Http/Controllers/ActivityController.php @@ -163,6 +163,6 @@ class ActivityController extends BaseController return response()->streamDownload(function () use ($pdf) { echo $pdf; - }, $filename); + }, $filename, ['Content-Type' => 'application/pdf']); } } diff --git a/app/Http/Controllers/ClientPortal/InvoiceController.php b/app/Http/Controllers/ClientPortal/InvoiceController.php index 0905bf74605b..fd360b9c8554 100644 --- a/app/Http/Controllers/ClientPortal/InvoiceController.php +++ b/app/Http/Controllers/ClientPortal/InvoiceController.php @@ -174,7 +174,7 @@ class InvoiceController extends Controller // return response()->download($file, basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true);; return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); + }, basename($file), ['Content-Type' => 'application/pdf']); } // enable output of HTTP headers diff --git a/app/Http/Controllers/ClientPortal/QuoteController.php b/app/Http/Controllers/ClientPortal/QuoteController.php index 39f2d5444da0..27deadf8c949 100644 --- a/app/Http/Controllers/ClientPortal/QuoteController.php +++ b/app/Http/Controllers/ClientPortal/QuoteController.php @@ -96,7 +96,7 @@ class QuoteController extends Controller // return response()->download($file, basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); + }, basename($file), ['Content-Type' => 'application/pdf']); } // enable output of HTTP headers diff --git a/app/Http/Controllers/CreditController.php b/app/Http/Controllers/CreditController.php index c8fb445a4293..6478dd1ebfbc 100644 --- a/app/Http/Controllers/CreditController.php +++ b/app/Http/Controllers/CreditController.php @@ -544,7 +544,7 @@ class CreditController extends BaseController return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); + }, basename($file), ['Content-Type' => 'application/pdf']); break; case 'archive': $this->credit_repository->archive($credit); @@ -596,8 +596,8 @@ class CreditController extends BaseController return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); - // return response()->download($file_path, basename($file_path), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); + }, basename($file), ['Content-Type' => 'application/pdf']); + } /** diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 4917e5e55e36..d7645f7b961d 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -672,16 +672,11 @@ class InvoiceController extends BaseController break; case 'download': - // $file = $invoice->pdf_file_path(); - // return response()->download($file, basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); - $file = $invoice->service()->getInvoicePdf(); - // return response()->download(Storage::get($file), basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); - return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); + }, basename($file), ['Content-Type' => 'application/pdf']); break; @@ -805,11 +800,9 @@ class InvoiceController extends BaseController $file = $invoice->service()->getInvoicePdf($contact); - // return response()->download(Storage::get($file), basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); - return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); + }, basename($file), ['Content-Type' => 'application/pdf']); } /** @@ -861,10 +854,9 @@ class InvoiceController extends BaseController $file = $invoice->service()->getInvoiceDeliveryNote($invoice, $invoice->invitations->first()->contact); - // return response()->download($file, basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); + }, basename($file), ['Content-Type' => 'application/pdf']); } diff --git a/app/Http/Controllers/PreviewController.php b/app/Http/Controllers/PreviewController.php index e0f30fb44fcb..9e87ba0bc291 100644 --- a/app/Http/Controllers/PreviewController.php +++ b/app/Http/Controllers/PreviewController.php @@ -11,11 +11,16 @@ namespace App\Http\Controllers; +use App\Factory\InvoiceFactory; +use App\Http\Requests\Invoice\StoreInvoiceRequest; +use App\Http\Requests\Preview\PreviewInvoiceRequest; use App\Jobs\Util\PreviewPdf; use App\Models\Client; use App\Models\ClientContact; use App\Models\Invoice; use App\Models\InvoiceInvitation; +use App\Repositories\InvoiceRepository; +use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\Design; use App\Services\PdfMaker\PdfMaker; use App\Utils\HostedPDF\NinjaPdf; @@ -149,6 +154,103 @@ class PreviewController extends BaseController return $this->blankEntity(); } + public function live(PreviewInvoiceRequest $request) + { + if(request()->input('entity') == 'invoice'){ + $repo = new InvoiceRepository(); + $factory = InvoiceFactory::create(auth()->user()->company()->id, auth()->user()->id); + } + + DB::connection(config('database.default'))->beginTransaction(); + + $entity = ucfirst(request()->input('entity')); + + // $class = "App\Models\\$entity"; + + // $entity_obj = $class::whereId($this->decodePrimaryKey(request()->input('entity_id')))->company()->first(); + + // if (! $entity_obj) { + + $entity_obj = $repo->save(request()->all(), $factory); + + // } + + $entity_obj->load('client'); + + App::forgetInstance('translator'); + $t = app('translator'); + App::setLocale($entity_obj->client->primary_contact()->first()->preferredLocale()); + $t->replace(Ninja::transformTranslations($entity_obj->client->getMergedSettings())); + + $html = new HtmlEngine($entity_obj->invitations()->first()); + + $design = \App\Models\Design::find($entity_obj->design_id); + + /* Catch all in case migration doesn't pass back a valid design */ + if(!$design) + $design = Design::find(2); + + if ($design->is_custom) { + $options = [ + 'custom_partials' => json_decode(json_encode($design->design), true) + ]; + $template = new PdfMakerDesign(PdfDesignModel::CUSTOM, $options); + } else { + $template = new PdfMakerDesign(strtolower($design->name)); + } + + $variables = $html->generateLabelsAndValues(); + + $state = [ + 'template' => $template->elements([ + 'client' => $entity_obj->client, + 'entity' => $entity_obj, + 'pdf_variables' => (array) $entity_obj->company->settings->pdf_variables, + '$product' => $design->design->product, + 'variables' => $variables, + ]), + 'variables' => $variables, + 'options' => [ + 'all_pages_header' => $entity_obj->client->getSetting('all_pages_header'), + 'all_pages_footer' => $entity_obj->client->getSetting('all_pages_footer'), + ], + ]; + + + $maker = new PdfMaker($state); + + $maker + ->design($template) + ->build(); + + if (request()->query('html') == 'true') { + return $maker->getCompiledHTML; + } + + DB::connection(config('database.default'))->rollBack(); + + //if phantom js...... inject here.. + if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { + return (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true)); + } + + if(config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja'){ + return (new NinjaPdf())->build($maker->getCompiledHTML(true)); + } + + //else + $file_path = PreviewPdf::dispatchNow($maker->getCompiledHTML(true), auth()->user()->company()); + + //return response()->download($file_path, basename($file_path), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); + + $response = Response::make($file_path, 200); + $response->header('Content-Type', 'application/pdf'); + + return $response; + + } + + private function blankEntity() { App::forgetInstance('translator'); diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index a867a7697168..3a073b374afd 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -682,7 +682,7 @@ class QuoteController extends BaseController return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); + }, basename($file), ['Content-Type' => 'application/pdf']); //return response()->download($file, basename($file), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); @@ -736,11 +736,10 @@ class QuoteController extends BaseController $quote = $invitation->quote; $file = $quote->service()->getQuotePdf($contact); -nlog($file); return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); + }, basename($file), ['Content-Type' => 'application/pdf']); // return response()->download($file_path, basename($file_path), ['Cache-Control:' => 'no-cache'])->deleteFileAfterSend(true); } diff --git a/app/Http/Controllers/RecurringInvoiceController.php b/app/Http/Controllers/RecurringInvoiceController.php index aef6b5e2e6ed..3bf2ea4e0809 100644 --- a/app/Http/Controllers/RecurringInvoiceController.php +++ b/app/Http/Controllers/RecurringInvoiceController.php @@ -505,7 +505,7 @@ class RecurringInvoiceController extends BaseController return response()->streamDownload(function () use($file) { echo Storage::get($file); - }, basename($file)); + }, basename($file), ['Content-Type' => 'application/pdf']); } diff --git a/app/Http/Controllers/SubdomainController.php b/app/Http/Controllers/SubdomainController.php index 14e0afa03461..7751eda00d85 100644 --- a/app/Http/Controllers/SubdomainController.php +++ b/app/Http/Controllers/SubdomainController.php @@ -26,6 +26,8 @@ class SubdomainController extends BaseController 'docs', 'client_domain', 'custom_domain', + 'preview', + 'invoiceninja', ]; public function __construct() diff --git a/app/Http/Requests/Preview/PreviewInvoiceRequest.php b/app/Http/Requests/Preview/PreviewInvoiceRequest.php new file mode 100644 index 000000000000..e7dc8f147217 --- /dev/null +++ b/app/Http/Requests/Preview/PreviewInvoiceRequest.php @@ -0,0 +1,59 @@ +user()->can('create', Invoice::class); + } + + public function rules() + { + $rules = []; + + $rules['client_id'] = 'bail|required|exists:clients,id,company_id,'.auth()->user()->company()->id; + + $rules['number'] = ['nullable']; + + return $rules; + } + + protected function prepareForValidation() + { + $input = $this->all(); + + $input = $this->decodePrimaryKeys($input); + + $input['line_items'] = isset($input['line_items']) ? $this->cleanItems($input['line_items']) : []; + $input['amount'] = 0; + $input['balance'] = 0; + + $this->replace($input); + } +} diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index bf6aac68ed11..89685ac11987 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -238,6 +238,10 @@ class Import implements ShouldQueue /*After a migration first some basic jobs to ensure the system is up to date*/ VersionCheck::dispatch(); + $account = $this->company->account; + $account->default_company_id = $this->company->id; + $account->save(); + //company size check if ($this->company->invoices()->count() > 1000 || $this->company->products()->count() > 1000 || $this->company->clients()->count() > 1000) { $this->company->is_large = true; diff --git a/app/Models/Presenters/CompanyPresenter.php b/app/Models/Presenters/CompanyPresenter.php index b550213277de..c9a7d9aafedc 100644 --- a/app/Models/Presenters/CompanyPresenter.php +++ b/app/Models/Presenters/CompanyPresenter.php @@ -27,7 +27,6 @@ class CompanyPresenter extends EntityPresenter return $this->settings->name ?: ctrans('texts.untitled_account'); - //return $this->entity->name ?: ctrans('texts.untitled_account'); } @@ -49,7 +48,7 @@ class CompanyPresenter extends EntityPresenter /** * Test for using base64 encoding */ - public function logo2($settings = null) + public function logo_base64($settings = null) { if (! $settings) { $settings = $this->entity->settings; diff --git a/app/Repositories/BaseRepository.php b/app/Repositories/BaseRepository.php index 51ba726ee75b..6e9906037166 100644 --- a/app/Repositories/BaseRepository.php +++ b/app/Repositories/BaseRepository.php @@ -300,7 +300,7 @@ class BaseRepository $model->partial = min($model->amount, $model->balance); /* Update product details if necessary */ - if ($model->company->update_products) + if ($model->company->update_products && $model->id) UpdateOrCreateProduct::dispatch($model->line_items, $model, $model->company); /* Perform model specific tasks */ diff --git a/app/Services/Quote/ConvertQuote.php b/app/Services/Quote/ConvertQuote.php index 648027eb9d69..94722341450c 100644 --- a/app/Services/Quote/ConvertQuote.php +++ b/app/Services/Quote/ConvertQuote.php @@ -40,6 +40,7 @@ class ConvertQuote $invoice->fresh(); $invoice->service() + ->fillDefaults() // ->markSent() // ->createInvitations() ->save(); diff --git a/resources/views/portal/ninja2020/components/general/sidebar/main.blade.php b/resources/views/portal/ninja2020/components/general/sidebar/main.blade.php index b907fe6a9f08..9d5cdb31a4bb 100644 --- a/resources/views/portal/ninja2020/components/general/sidebar/main.blade.php +++ b/resources/views/portal/ninja2020/components/general/sidebar/main.blade.php @@ -4,6 +4,7 @@ @keydown.window.escape="sidebarOpen = false" id="main-sidebar"> + @if($settings->enable_client_portal) @include('portal.ninja2020.components.general.sidebar.mobile') @@ -12,6 +13,8 @@ @include('portal.ninja2020.components.general.sidebar.desktop') @endunless + @endif +