diff --git a/app/Events/QuoteApproved.php b/app/Events/QuoteApproved.php new file mode 100644 index 000000000000..12b5384b35e3 --- /dev/null +++ b/app/Events/QuoteApproved.php @@ -0,0 +1,23 @@ +invoice = $invoice; + } + +} diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 44aa7a0c5e22..24025cc0f835 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -554,6 +554,7 @@ class AccountController extends BaseController $user->notify_sent = Input::get('notify_sent'); $user->notify_viewed = Input::get('notify_viewed'); $user->notify_paid = Input::get('notify_paid'); + $user->notify_approved = Input::get('notify_approved'); $user->save(); Session::flash('message', trans('texts.updated_settings')); diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index 93181e628b83..378830c5bd43 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -6,7 +6,8 @@ use Redirect; use Utils; use View; use Cache; - +use Event; +use Session; use App\Models\Account; use App\Models\Client; use App\Models\Country; @@ -17,10 +18,13 @@ use App\Models\PaymentTerm; use App\Models\Product; use App\Models\Size; use App\Models\TaxRate; +use App\Models\Invitation; +use App\Models\Activity; use App\Ninja\Mailers\ContactMailer as Mailer; use App\Ninja\Repositories\InvoiceRepository; use App\Ninja\Repositories\ClientRepository; use App\Ninja\Repositories\TaxRateRepository; +use App\Events\QuoteApproved; class QuoteController extends BaseController { @@ -187,7 +191,9 @@ class QuoteController extends BaseController $invoice = $invitation->invoice; if ($invoice->is_quote && !$invoice->quote_invoice_id) { - Activity::approveQuote($invitation); + Event::fire(new QuoteApproved($invoice)); + Activity::approveQuote($invitation); + $invoice = $this->invoiceRepo->cloneInvoice($invoice, $invoice->id); Session::flash('message', trans('texts.converted_to_invoice')); diff --git a/app/Listeners/HandleQuoteApproved.php b/app/Listeners/HandleQuoteApproved.php new file mode 100644 index 000000000000..3a49aa9b5af5 --- /dev/null +++ b/app/Listeners/HandleQuoteApproved.php @@ -0,0 +1,42 @@ +userMailer = $userMailer; + } + + /** + * Handle the event. + * + * @param QuoteApproved $event + * @return void + */ + public function handle(QuoteApproved $event) + { + $invoice = $event->invoice; + + foreach ($invoice->account->users as $user) + { + if ($user->{'notify_approved'}) + { + $this->userMailer->sendNotification($user, $invoice, 'approved'); + } + } + } + +} diff --git a/app/Ninja/Mailers/UserMailer.php b/app/Ninja/Mailers/UserMailer.php index ad82923b7727..5831e66b5cdc 100644 --- a/app/Ninja/Mailers/UserMailer.php +++ b/app/Ninja/Mailers/UserMailer.php @@ -39,8 +39,8 @@ class UserMailer extends Mailer return; } - $view = 'invoice_'.$notificationType; $entityType = $invoice->getEntityType(); + $view = "{$entityType}_{$notificationType}"; $data = [ 'entityType' => $entityType, diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index 5bfbcdd7c187..10631eb15112 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -223,6 +223,17 @@ class InvoiceRepository $account = \Auth::user()->account; + if ((isset($data['set_default_terms']) && $data['set_default_terms']) + || (isset($data['set_default_footer']) && $data['set_default_footer'])) { + if (isset($data['set_default_terms']) && $data['set_default_terms']) { + $account->invoice_terms = trim($data['terms']); + } + if (isset($data['set_default_footer']) && $data['set_default_footer']) { + $account->invoice_footer = trim($data['invoice_footer']); + } + $account->save(); + } + $invoice->client_id = $data['client_id']; $invoice->discount = round(Utils::parseFloat($data['discount']), 2); $invoice->is_amount_discount = $data['is_amount_discount'] ? true : false; @@ -360,17 +371,6 @@ class InvoiceRepository $invoice->invoice_items()->save($invoiceItem); } - if ((isset($data['set_default_terms']) && $data['set_default_terms']) - || (isset($data['set_default_footer']) && $data['set_default_footer'])) { - if (isset($data['set_default_terms']) && $data['set_default_terms']) { - $account->invoice_terms = trim($data['terms']); - } - if (isset($data['set_default_footer']) && $data['set_default_footer']) { - $account->invoice_footer = trim($data['invoice_footer']); - } - $account->save(); - } - return $invoice; } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index e5fd505a007a..3ce33b355412 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -26,6 +26,9 @@ class EventServiceProvider extends ServiceProvider { 'App\Events\InvoicePaid' => [ 'App\Listeners\HandleInvoicePaid', ], + 'App\Events\QuoteApproved' => [ + 'App\Listeners\HandleQuoteApproved', + ], ]; /** diff --git a/database/migrations/2015_04_13_100333_add_notify_approved.php b/database/migrations/2015_04_13_100333_add_notify_approved.php new file mode 100644 index 000000000000..8f0a4fd74060 --- /dev/null +++ b/database/migrations/2015_04_13_100333_add_notify_approved.php @@ -0,0 +1,34 @@ +boolean('notify_approved')->default(true); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function($table) + { + $table->dropColumn('notify_approved'); + }); + } + +} diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php index 80cda729a834..20a2071c809c 100644 --- a/resources/lang/da/texts.php +++ b/resources/lang/da/texts.php @@ -580,5 +580,9 @@ return array( 'send_email' => 'Send email', 'set_password' => 'Set Password', 'converted' => 'Converted', + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', ); diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php index cdb8b241bc4d..5b1da59faecd 100644 --- a/resources/lang/de/texts.php +++ b/resources/lang/de/texts.php @@ -571,6 +571,10 @@ return array( 'send_email' => 'Send email', 'set_password' => 'Set Password', 'converted' => 'Converted', + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', ); diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 8c3959020dc3..a8ad30ccc7a2 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -578,6 +578,9 @@ return array( 'send_email' => 'Send email', 'set_password' => 'Set Password', 'converted' => 'Converted', - - + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', + ); diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php index 2a06257d8c4b..5cedb7aa5154 100644 --- a/resources/lang/es/texts.php +++ b/resources/lang/es/texts.php @@ -550,7 +550,11 @@ return array( 'send_email' => 'Send email', 'set_password' => 'Set Password', 'converted' => 'Converted', - + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', + ); \ No newline at end of file diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php index 09a5a4339072..94836f2f68d0 100644 --- a/resources/lang/fr/texts.php +++ b/resources/lang/fr/texts.php @@ -571,6 +571,10 @@ return array( 'send_email' => 'Send email', 'set_password' => 'Set Password', 'converted' => 'Converted', - + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', + ); \ No newline at end of file diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php index 4bc0f7f0a59c..83af0c1028a8 100644 --- a/resources/lang/it/texts.php +++ b/resources/lang/it/texts.php @@ -573,6 +573,10 @@ return array( 'send_email' => 'Send email', 'set_password' => 'Set Password', 'converted' => 'Converted', + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', ); diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php index f78284d8bb7f..96ab93f6d9ae 100644 --- a/resources/lang/lt/texts.php +++ b/resources/lang/lt/texts.php @@ -581,6 +581,10 @@ return array( 'send_email' => 'Send email', 'set_password' => 'Set Password', 'converted' => 'Converted', + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php index f87c1fa93129..ec63a0dbfc5a 100644 --- a/resources/lang/nb_NO/texts.php +++ b/resources/lang/nb_NO/texts.php @@ -580,5 +580,9 @@ return array( 'set_password' => 'Set Password', 'converted' => 'Converted', + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', + ); \ No newline at end of file diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php index 4c4b3e13c117..e4634a64f09b 100644 --- a/resources/lang/nl/texts.php +++ b/resources/lang/nl/texts.php @@ -574,6 +574,10 @@ return array( 'send_email' => 'Verstuur email', 'set_password' => 'Stel wachtwoord in', 'converted' => 'Omgezet', + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php index bac1303054a9..639eae4378ff 100644 --- a/resources/lang/pt_BR/texts.php +++ b/resources/lang/pt_BR/texts.php @@ -574,6 +574,10 @@ return array( 'send_email' => 'Send email', 'set_password' => 'Set Password', 'converted' => 'Converted', + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', ); diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php index 755c5bd5a211..3185222c1eed 100644 --- a/resources/lang/sv/texts.php +++ b/resources/lang/sv/texts.php @@ -577,6 +577,10 @@ return array( 'send_email' => 'Skicka mail', 'set_password' => 'Ange lösenord', 'converted' => 'Konvertera', + + 'email_approved' => 'Email me when a quote is approved', + 'notification_quote_approved_subject' => 'Quote :invoice was approved by :client', + 'notification_quote_approved' => 'The following client :client approved Quote :invoice for :amount.', ); diff --git a/resources/views/accounts/notifications.blade.php b/resources/views/accounts/notifications.blade.php index 15f9915d162f..0e4fe6f73b88 100644 --- a/resources/views/accounts/notifications.blade.php +++ b/resources/views/accounts/notifications.blade.php @@ -8,11 +8,13 @@ {{ Former::populateField('notify_sent', intval(Auth::user()->notify_sent)) }} {{ Former::populateField('notify_viewed', intval(Auth::user()->notify_viewed)) }} {{ Former::populateField('notify_paid', intval(Auth::user()->notify_paid)) }} + {{ Former::populateField('notify_approved', intval(Auth::user()->notify_approved)) }} {!! Former::legend(trans('texts.email_notifications')) !!} {!! Former::checkbox('notify_sent')->label(' ')->text(trans('texts.email_sent')) !!} {!! Former::checkbox('notify_viewed')->label(' ')->text(trans('texts.email_viewed')) !!} - {!! Former::checkbox('notify_paid')->label(' ')->text(trans('texts.email_paid')) !!} + {!! Former::checkbox('notify_paid')->label(' ')->text(trans('texts.email_paid')) !!} + {!! Former::checkbox('notify_approved')->label(' ')->text(trans('texts.email_approved')) !!} {!! Former::legend(trans('texts.site_updates')) !!} diff --git a/resources/views/emails/quote_approved_html.blade.php b/resources/views/emails/quote_approved_html.blade.php new file mode 100644 index 000000000000..0bcc50acfab4 --- /dev/null +++ b/resources/views/emails/quote_approved_html.blade.php @@ -0,0 +1,18 @@ + + + + + + + @include('emails.view_action', ['link' => $invoiceLink, 'entityType' => $entityType]) + {{ trans('texts.email_salutation', ['name' => $userName]) }}

+ + {{ trans("texts.notification_{$entityType}_approved", ['amount' => $invoiceAmount, 'client' => $clientName, 'invoice' => $invoiceNumber]) }}

+ + {{ trans('texts.email_signature') }}
+ {{ trans('texts.email_from') }}

+ + {{ trans('texts.user_email_footer') }}

+ + + \ No newline at end of file diff --git a/resources/views/emails/quote_approved_text.blade.php b/resources/views/emails/quote_approved_text.blade.php new file mode 100644 index 000000000000..826b18e7d58e --- /dev/null +++ b/resources/views/emails/quote_approved_text.blade.php @@ -0,0 +1,8 @@ +{{ trans('texts.email_salutation', ['name' => $userName]) }} + +{{ trans("texts.notification_{$entityType}_approved", ['amount' => $invoiceAmount, 'client' => $clientName, 'invoice' => $invoiceNumber]) }} + +{{ trans('texts.email_signature') }} +{{ trans('texts.email_from') }} + +{{ trans('texts.user_email_footer') }} \ No newline at end of file diff --git a/resources/views/invoices/edit.blade.php b/resources/views/invoices/edit.blade.php index 2bf24232c4e8..7be74e42d1c4 100644 --- a/resources/views/invoices/edit.blade.php +++ b/resources/views/invoices/edit.blade.php @@ -1181,8 +1181,8 @@ self.totals.rawSubtotal = ko.computed(function() { var total = 0; for(var p=0; p < self.invoice_items().length; ++p) { - var item = self.invoice_items()[p]; - total += item.totals.rawTotal(); + var item = self.invoice_items()[p]; + total += item.totals.rawTotal(); } return total; }); @@ -1526,12 +1526,12 @@ var cost = roundToTwo(NINJA.parseFloat(self.cost())); var qty = roundToTwo(NINJA.parseFloat(self.qty())); var taxRate = NINJA.parseFloat(self.tax_rate()); - var value = cost * qty; - if (taxRate > 0) { - value += value * (taxRate/100); - } - return value ? roundToTwo(value) : ''; - }); + var value = cost * qty; + if (taxRate > 0) { + value += value * (taxRate/100); + } + return value ? roundToTwo(value) : 0; + }); this.totals.total = ko.computed(function() { var total = self.totals.rawTotal(); diff --git a/resources/views/invoices/view.blade.php b/resources/views/invoices/view.blade.php index 0f6f768343bf..6caa93395dc6 100644 --- a/resources/views/invoices/view.blade.php +++ b/resources/views/invoices/view.blade.php @@ -24,7 +24,7 @@ @if ($invoice->is_quote) {!! Button::normal(trans('texts.download_pdf'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}   @if (!$isConverted) - {!! Button::success(trans('texts.approve'))->asLinkTo('approve/' . $invitation->invitation_key)->large() !!} + {!! Button::success(trans('texts.approve'))->asLinkTo('/approve/' . $invitation->invitation_key)->large() !!} @endif @elseif ($invoice->client->account->isGatewayConfigured() && !$invoice->isPaid() && !$invoice->is_recurring) {!! Button::normal(trans('texts.download_pdf'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}   @@ -39,10 +39,10 @@ ['url' => URL::to("payment/{$invitation->invitation_key}?use_paypal=false"), 'label' => trans('texts.pay_with_card')] ])->addClass('btn-lg') !!} @else - {!! Button::success(trans('texts.pay_now'))->asLinkTo(URL::to('payment/' . $invitation->invitation_key))->large() !!} + {!! Button::success(trans('texts.pay_now'))->asLinkTo('/payment/' . $invitation->invitation_key)->large() !!} @endif @else - {!! Button::success('Download PDF')->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!} + {!! Button::normal('Download PDF')->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!} @endif