diff --git a/app/Http/Controllers/Incomes/Invoices.php b/app/Http/Controllers/Incomes/Invoices.php index f479b48e7..85571ffdf 100644 --- a/app/Http/Controllers/Incomes/Invoices.php +++ b/app/Http/Controllers/Incomes/Invoices.php @@ -446,7 +446,7 @@ class Invoices extends Controller $invoice->paid = $paid; - $invoice->template_path = 'incomes.invoices.print'; + $invoice->template_path = 'incomes.invoices.print_' . setting('invoice.template' ,'default'); event(new \App\Events\Income\InvoicePrinting($invoice)); diff --git a/app/Http/Controllers/Modals/InvoiceTemplates.php b/app/Http/Controllers/Modals/InvoiceTemplates.php new file mode 100644 index 000000000..29c1e85a0 --- /dev/null +++ b/app/Http/Controllers/Modals/InvoiceTemplates.php @@ -0,0 +1,126 @@ +middleware('permission:create-settings-settings')->only(['create', 'store']); + $this->middleware('permission:read-settings-settings')->only(['index', 'edit']); + $this->middleware('permission:update-settings-settings')->only(['update', 'enable', 'disable']); + $this->middleware('permission:delete-settings-settings')->only('destroy'); + } + + /** + * Update the specified resource in storage. + * + * @param Request $request + * + * @return Response + */ + public function update(Request $request) + { + $fields = $request->all(); + $prefix = $request->get('_prefix', 'general'); + $company_id = $request->get('company_id'); + + if (empty($company_id)) { + $company_id = session('company_id'); + } + + $company = Company::find($company_id); + + $companies = Company::all()->count(); + + foreach ($fields as $key => $value) { + $real_key = $prefix . '.' . $key; + + // Don't process unwanted keys + if (in_array($key, $this->skip_keys)) { + continue; + } + + // Process file uploads + if (in_array($real_key, $this->file_keys)) { + // Upload attachment + if ($request->file($key)) { + $media = $this->getMedia($request->file($key), 'settings'); + + $company->attachMedia($media, Str::snake($real_key)); + + $value = $media->id; + } + + // Prevent reset + if (empty($value)) { + continue; + } + } + + if ($real_key == 'default.locale') { + user()->setAttribute('locale', $value)->save(); + } + + // If only 1 company + if ($companies == 1) { + $this->oneCompany($real_key, $value); + } + + setting()->set($real_key, $value); + } + + // Save all settings + setting()->save(); + + $message = trans('messages.success.updated', ['type' => trans_choice('general.settings', 2)]); + + $response = [ + 'status' => null, + 'success' => true, + 'error' => false, + 'message' => $message, + 'data' => null, + 'redirect' => route('settings.invoice.edit'), + ]; + + flash($message)->success(); + + return response()->json($response); + } + + protected function oneCompany($real_key, $value) + { + switch ($real_key) { + case 'company.name': + Installer::updateEnv(['MAIL_FROM_NAME' => '"' . $value . '"']); + break; + case 'company.email': + Installer::updateEnv(['MAIL_FROM_ADDRESS' => $value]); + break; + case 'default.locale': + Installer::updateEnv(['APP_LOCALE' => $value]); + break; + case 'schedule.time': + Installer::updateEnv(['APP_SCHEDULE_TIME' => '"' . $value . '"']); + break; + } + } +} diff --git a/app/Providers/ViewComposer.php b/app/Providers/ViewComposer.php index bddc9a277..5cc902e17 100644 --- a/app/Providers/ViewComposer.php +++ b/app/Providers/ViewComposer.php @@ -58,7 +58,7 @@ class ViewComposer extends Provider // Add logo View::composer( - ['expenses.bills.print', 'expenses.bills.show', 'incomes.invoices.print', 'incomes.invoices.show', 'portal.invoices.show'], + ['expenses.bills.print', 'expenses.bills.show', 'incomes.invoices.print_default', 'incomes.invoices.print_classic', 'incomes.invoices.print_modern', 'incomes.invoices.show', 'portal.invoices.show'], 'App\Http\ViewComposers\Logo' ); diff --git a/public/css/custom.css b/public/css/custom.css index 208fe9eba..17e048c34 100644 --- a/public/css/custom.css +++ b/public/css/custom.css @@ -148,6 +148,14 @@ /*--------Border Radius 0 Finished--------*/ +/*--------Border Radius 5--------*/ +.border-radius-5 +{ + border-radius: 5px !important; +} +/*--------Border Radius 5 Finished--------*/ + + .dropup .dropdown-toggle::after { display: none !important; @@ -749,6 +757,57 @@ table .align-items-center td span.badge { font-size: 9px; } +/*--------Print Template--------*/ +.choose +{ + cursor: pointer; +} + +.choose:hover > img +{ + opacity: 0.50 !important; +} + +.bg-print +{ + background-color: rgba(229, 229, 229, 0.4)!important;; +} + +.print-edge +{ + width: 147px; +} + +/*--------Border Dashed--------*/ +.border-dashed +{ + border-top: 1px dashed #3c3f72 !important; +} +/*--------Border Dashed Finish--------*/ + +.invoice-classic-line +{ + border: 2px solid #3c3f72; + border-radius: 5px; +} + +.invoice-classic-frame +{ + width: 100%; + height:100px; + border: 3px solid #3c3f72; +} + +.invoice-classic-inline-frame +{ + margin: 7px 1%; + width: 98%; + height: 80px; + border: 3px solid #3c3f72; +} +/*--------Print Template Finish--------*/ + + /*----------------RESPONSIVE START LINE----------------*/ /*--------Xs Breakpoint--------*/ @media (min-width: 304px) and (max-width: 575.98px) diff --git a/public/img/print_templates/classic.png b/public/img/print_templates/classic.png new file mode 100644 index 000000000..705422f51 Binary files /dev/null and b/public/img/print_templates/classic.png differ diff --git a/public/img/print_templates/default.png b/public/img/print_templates/default.png new file mode 100644 index 000000000..9e360346c Binary files /dev/null and b/public/img/print_templates/default.png differ diff --git a/public/img/print_templates/modern.png b/public/img/print_templates/modern.png new file mode 100644 index 000000000..d0e92a220 Binary files /dev/null and b/public/img/print_templates/modern.png differ diff --git a/resources/assets/js/views/settings/settings.js b/resources/assets/js/views/settings/settings.js index 78684bbde..5bda7a744 100644 --- a/resources/assets/js/views/settings/settings.js +++ b/resources/assets/js/views/settings/settings.js @@ -36,6 +36,14 @@ const app = new Vue({ smtpUsername:true, smtpPassword:true, smtpEncryption:true, + }, + invoice_form: new Form('template'), + template: { + modal: false, + title: '', + message: '', + html: '', + errors: new Error() } } }, @@ -72,6 +80,31 @@ const app = new Vue({ this.email.smtpEncryption = true; break; } - } + }, + + onTemplate() { + this.template.modal = true; + + this.invoice_form = new Form('template'); + + this.invoice_form.template = this.invoice_form._template; + }, + + addTemplate() { + if (this.invoice_form.template != 1) { + this.invoice_form.submit(); + + this.template.errors = this.invoice_form.errors; + } + }, + + closeTemplate() { + this.template = { + modal: false, + title: '', + message: '', + errors: this.invoice_form.errors + }; + }, } }); diff --git a/resources/lang/en-GB/settings.php b/resources/lang/en-GB/settings.php index b263d1a28..07716b360 100644 --- a/resources/lang/en-GB/settings.php +++ b/resources/lang/en-GB/settings.php @@ -52,6 +52,11 @@ return [ 'subheading' => 'Subheading', 'due_receipt' => 'Due upon receipt', 'due_days' => 'Due within :days days', + 'invoice_template' => 'Invoice Template', + 'choose_template' => 'Choose a template', + 'default' => 'Default', + 'classic' => 'Classic', + 'modern' => 'Modern', ], 'default' => [ diff --git a/resources/views/incomes/invoices/print.blade.php b/resources/views/incomes/invoices/print.blade.php deleted file mode 100644 index eb9840940..000000000 --- a/resources/views/incomes/invoices/print.blade.php +++ /dev/null @@ -1,282 +0,0 @@ -@extends('layouts.print') - -@section('title', trans_choice('general.invoices', 1) . ': ' . $invoice->invoice_number) - -@section('content') -
- |
-
---|
- {{ setting('company.name') }} - | -
---|
- {!! nl2br(setting('company.address')) !!} - | -
- @if (setting('company.tax_number')) - {{ trans('general.tax_number') }}: {{ setting('company.tax_number') }} - @endif - | -
- @if (setting('company.phone')) - {{ setting('company.phone') }} - @endif - | -
- {{ setting('company.email') }} - | -
- {{ trans('invoices.bill_to') }} - @stack('name_input_start') - {{ $invoice->contact_name }} - @stack('name_input_end') - | -
---|
- @stack('address_input_start') - {!! nl2br($invoice->contact_address) !!} - @stack('address_input_end') - | -
- @stack('tax_number_input_start')
- @if ($invoice->contact_tax_number)
- {{ trans('general.tax_number') }}: {{ $invoice->contact_tax_number }} - @endif - @stack('tax_number_input_end') - |
-
- @stack('phone_input_start') - @if ($invoice->contact_phone) - {{ $invoice->contact_phone }} - @endif - @stack('phone_input_end') - | -
- @stack('email_start') - {{ $invoice->contact_email }} - @stack('email_input_end') - | -
{{ trans('invoices.invoice_number') }}: | -{{ $invoice->invoice_number }} | -
---|---|
{{ trans('invoices.order_number') }}: | -{{ $invoice->order_number }} | -
{{ trans('invoices.invoice_date') }}: | -@date($invoice->invoiced_at) | -
{{ trans('invoices.payment_due') }}: | -@date($invoice->due_at) | -
{{ trans_choice($text_override['items'], 2) }} | - @stack('name_th_end') - - @stack('quantity_th_start') -{{ trans($text_override['quantity']) }} | - @stack('quantity_th_end') - - @stack('price_th_start') -{{ trans($text_override['price']) }} | - @stack('price_th_end') - - @stack('total_th_start') -{{ trans('invoices.total') }} | - @stack('total_th_end') -
---|---|---|---|
- {{ $item->name }}
- @if ($item->desc)
- {!! $item->desc !!} - @endif - |
- @stack('name_td_end')
-
- @stack('quantity_td_start')
- {{ $item->quantity }} | - @stack('quantity_td_end') - - @stack('price_td_start') -@money($item->price, $invoice->currency_code, true) | - @stack('price_td_end') - - @stack('total_td_start') -@money($item->total, $invoice->currency_code, true) | - @stack('total_td_end') -
- {{ trans_choice('general.notes', 2) }} -{{ $invoice->notes }} - |
-
---|
- {{ trans($total->title) }}: - | -- @money($total->amount, $invoice->currency_code, true) - | -
---|---|
- {{ trans('invoices.paid') }}: - | -- - @money($invoice->paid, $invoice->currency_code, true) - | -
- {{ trans($total->name) }}: - | -- @money($total->amount - $invoice->paid, $invoice->currency_code, true) - | -
- {!! $invoice->footer !!} - | -
---|
+ {{ setting('company.name') }} +
+ ++ {!! nl2br(setting('company.address')) !!} +
+ ++ @if (setting('company.tax_number')) + {{ trans('general.tax_number') }}: {{ setting('company.tax_number') }} + @endif +
+ ++ @if (setting('company.phone')) + {{ setting('company.phone') }} + @endif +
+ ++ {{ setting('company.email') }} +
++ {{ trans('invoices.invoice_number') }}: + {{ $invoice->invoice_number }} +
+ @stack('invoice_number_input_end') ++ {!! nl2br($invoice->contact_address) !!} +
+ @stack('address_input_end') + + @stack('tax_number_input_start') +
+ @if ($invoice->contact_tax_number)
+ {{ trans('general.tax_number') }}: {{ $invoice->contact_tax_number }}
+ @endif
+
+ @if ($invoice->contact_phone) + {{ $invoice->contact_phone }} + @endif +
+ @stack('phone_input_end') + + @stack('email_start') ++ {{ $invoice->contact_email }} +
+ @stack('email_input_end') + ++ {{ trans('invoices.order_number') }}: + {{ $invoice->order_number }} +
+ @endif + @stack('order_number_input_end') + + @stack('invoiced_at_input_start') ++ {{ trans('invoices.invoice_date') }}: + @date($invoice->invoiced_at) +
+ @stack('invoiced_at_input_end') + + @stack('due_at_input_start') ++ {{ trans('invoices.payment_due') }}: + @date($invoice->due_at) +
+ @stack('due_at_input_end') + + @foreach ($invoice->totals as $total) + @if ($total->code == 'total') ++ {{ trans($total->name) }}: + @money($total->amount - $invoice->paid, $invoice->currency_code, true) +
+ @endif + @endforeach +{{ trans_choice($text_override['items'], 2) }} | + @stack('name_th_end') + + @stack('quantity_th_start') +{{ trans($text_override['quantity']) }} | + @stack('quantity_th_end') + + @stack('price_th_start') +{{ trans($text_override['price']) }} | + @stack('price_th_end') + + @stack('total_th_start') +{{ trans('invoices.total') }} | + @stack('total_th_end') +
---|---|---|---|
+ {{ $item->name }}
+ @if ($item->desc)
+ {!! $item->desc !!} + @endif + |
+ @stack('name_td_end')
+
+ @stack('quantity_td_start')
+ {{ $item->quantity }} | + @stack('quantity_td_end') + + @stack('price_td_start') +@money($item->price, $invoice->currency_code, true) | + @stack('price_td_end') + + @stack('total_td_start') +@money($item->total, $invoice->currency_code, true) | + @stack('total_td_end') +
+ {{ trans_choice('general.notes', 2) }} +{{ $invoice->notes }} + |
+
---|
+ {{ trans($total->title) }}: + | ++ @money($total->amount, $invoice->currency_code, true) + | +
---|---|
+ {{ trans('invoices.paid') }}: + | ++ - @money($invoice->paid, $invoice->currency_code, true) + | +
+ {{ trans($total->name) }}: + | ++ @money($total->amount - $invoice->paid, $invoice->currency_code, true) + | +
+ {!! $invoice->footer !!} + | +
---|
+ |
+
---|
+ {{ setting('company.name') }} + | +
---|
+ {!! nl2br(setting('company.address')) !!} + | +
+ @if (setting('company.tax_number')) + {{ trans('general.tax_number') }}: {{ setting('company.tax_number') }} + @endif + | +
+ @if (setting('company.phone')) + {{ setting('company.phone') }} + @endif + | +
+ {{ setting('company.email') }} + | +
+ {{ trans('invoices.bill_to') }} + @stack('name_input_start') + {{ $invoice->contact_name }} + @stack('name_input_end') + | +
---|
+ @stack('address_input_start') + {!! nl2br($invoice->contact_address) !!} + @stack('address_input_end') + | +
+ @stack('tax_number_input_start')
+ @if ($invoice->contact_tax_number)
+ {{ trans('general.tax_number') }}: {{ $invoice->contact_tax_number }} + @endif + @stack('tax_number_input_end') + |
+
+ @stack('phone_input_start') + @if ($invoice->contact_phone) + {{ $invoice->contact_phone }} + @endif + @stack('phone_input_end') + | +
+ @stack('email_start') + {{ $invoice->contact_email }} + @stack('email_input_end') + | +
{{ trans('invoices.invoice_number') }}: | +{{ $invoice->invoice_number }} | +
---|---|
{{ trans('invoices.order_number') }}: | +{{ $invoice->order_number }} | +
{{ trans('invoices.invoice_date') }}: | +@date($invoice->invoiced_at) | +
{{ trans('invoices.payment_due') }}: | +@date($invoice->due_at) | +
{{ trans_choice($text_override['items'], 2) }} | + @stack('name_th_end') + + @stack('quantity_th_start') +{{ trans($text_override['quantity']) }} | + @stack('quantity_th_end') + + @stack('price_th_start') +{{ trans($text_override['price']) }} | + @stack('price_th_end') + + @stack('total_th_start') +{{ trans('invoices.total') }} | + @stack('total_th_end') +
---|---|---|---|
+ {{ $item->name }}
+ @if ($item->desc)
+ {!! $item->desc !!} + @endif + |
+ @stack('name_td_end')
+
+ @stack('quantity_td_start')
+ {{ $item->quantity }} | + @stack('quantity_td_end') + + @stack('price_td_start') +@money($item->price, $invoice->currency_code, true) | + @stack('price_td_end') + + @stack('total_td_start') +@money($item->total, $invoice->currency_code, true) | + @stack('total_td_end') +
+ {{ trans_choice('general.notes', 2) }} +{{ $invoice->notes }} + |
+
---|
+ {{ trans($total->title) }}: + | ++ @money($total->amount, $invoice->currency_code, true) + | +
---|---|
+ {{ trans('invoices.paid') }}: + | ++ - @money($invoice->paid, $invoice->currency_code, true) + | +
+ {{ trans($total->name) }}: + | ++ @money($total->amount - $invoice->paid, $invoice->currency_code, true) + | +
+ {!! $invoice->footer !!} + | +
---|
+ {{ setting('company.name') }}+ |
+
---|
+ {!! nl2br(setting('company.address')) !!} + | +
---|
+ @if (setting('company.tax_number')) + {{ trans('general.tax_number') }}: {{ setting('company.tax_number') }} + @endif + | +
+ @if (setting('company.phone')) + {{ setting('company.phone') }} + @endif + | +
+ {{ setting('company.email') }} + | +
+ {{ trans('invoices.bill_to') }}+ @stack('name_input_start') + {{ $invoice->contact_name }} + @stack('name_input_end') + |
+
---|
+ @stack('address_input_start') + {!! nl2br($invoice->contact_address) !!} + @stack('address_input_end') + | +
+ @stack('tax_number_input_start')
+ @if ($invoice->contact_tax_number)
+ {{ trans('general.tax_number') }}: {{ $invoice->contact_tax_number }} + @endif + @stack('tax_number_input_end') + |
+
+ @stack('phone_input_start') + @if ($invoice->contact_phone) + {{ $invoice->contact_phone }} + @endif + @stack('phone_input_end') + | +
+ @stack('email_start') + {{ $invoice->contact_email }} + @stack('email_input_end') + | +
{{ trans('invoices.invoice_number') }}: | +{{ $invoice->invoice_number }} | +
---|---|
{{ trans('invoices.order_number') }}: | +{{ $invoice->order_number }} | +
{{ trans('invoices.invoice_date') }}: | +@date($invoice->invoiced_at) | +
{{ trans('invoices.payment_due') }}: | +@date($invoice->due_at) | +
{{ trans_choice($text_override['items'], 2) }} | + @stack('name_th_end') + + @stack('quantity_th_start') +{{ trans($text_override['quantity']) }} | + @stack('quantity_th_end') + + @stack('price_th_start') +{{ trans($text_override['price']) }} | + @stack('price_th_end') + + @stack('total_th_start') +{{ trans('invoices.total') }} | + @stack('total_th_end') +
---|---|---|---|
+ {{ $item->name }}
+ @if ($item->desc)
+ {!! $item->desc !!} + @endif + |
+ @stack('name_td_end')
+
+ @stack('quantity_td_start')
+ {{ $item->quantity }} | + @stack('quantity_td_end') + + @stack('price_td_start') +@money($item->price, $invoice->currency_code, true) | + @stack('price_td_end') + + @stack('total_td_start') +@money($item->total, $invoice->currency_code, true) | + @stack('total_td_end') +
+ {{ trans_choice('general.notes', 2) }} +{{ $invoice->notes }} + |
+
---|
+ {{ trans($total->title) }}: + | ++ @money($total->amount, $invoice->currency_code, true) + | +
---|---|
+ {{ trans('invoices.paid') }}: + | ++ - @money($invoice->paid, $invoice->currency_code, true) + | +
+ {{ trans($total->name) }}: + | ++ @money($total->amount - $invoice->paid, $invoice->currency_code, true) + | +
+ {!! $invoice->footer !!} + | +
---|