From f119a6f74c6070db5689cfebf1de14db57478d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristia=CC=81n=20Feldsam?= Date: Mon, 29 Apr 2019 10:57:45 +0200 Subject: [PATCH 1/5] Add option to disable requiring quote approving MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristián Feldsam --- app/Http/Controllers/AccountController.php | 1 + .../Controllers/ClientPortalController.php | 3 +- app/Models/Account.php | 2 ++ app/Models/Invoice.php | 10 +++++- ...04_29_073828_add_require_approve_quote.php | 32 +++++++++++++++++++ resources/lang/en/texts.php | 2 ++ .../views/accounts/invoice_settings.blade.php | 5 +++ resources/views/invoices/view.blade.php | 2 +- 8 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 database/migrations/2019_04_29_073828_add_require_approve_quote.php diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 9ec3fea97ef9..2435f70119e8 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -1065,6 +1065,7 @@ class AccountController extends BaseController $account->quote_terms = Input::get('quote_terms'); $account->auto_convert_quote = Input::get('auto_convert_quote'); $account->auto_archive_quote = Input::get('auto_archive_quote'); + $account->require_approve_quote = Input::get('require_approve_quote'); $account->allow_approve_expired_quote = Input::get('allow_approve_expired_quote'); $account->auto_archive_invoice = Input::get('auto_archive_invoice'); $account->auto_email_invoice = Input::get('auto_email_invoice'); diff --git a/app/Http/Controllers/ClientPortalController.php b/app/Http/Controllers/ClientPortalController.php index e1f27d331fbc..4bf1c92849d8 100644 --- a/app/Http/Controllers/ClientPortalController.php +++ b/app/Http/Controllers/ClientPortalController.php @@ -146,13 +146,14 @@ class ClientPortalController extends BaseController } } - $showApprove = $invoice->quote_invoice_id ? false : true; + $showApprove = ($invoice->isQuote() && $account->require_approve_quote) ? true: false; if ($invoice->invoice_status_id >= INVOICE_STATUS_APPROVED) { $showApprove = false; } $data += [ 'account' => $account, + 'approveRequired' => $account->require_approve_quote, 'showApprove' => $showApprove, 'showBreadcrumbs' => false, 'invoice' => $invoice->hidePrivateFields(), diff --git a/app/Models/Account.php b/app/Models/Account.php index 008c99e7e941..2bfd0916dbca 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -109,6 +109,8 @@ class Account extends Eloquent 'body_font_id', 'auto_convert_quote', 'auto_archive_quote', + 'require_approve_quote', + 'allow_approve_expired_quote', 'auto_archive_invoice', 'auto_email_invoice', 'all_pages_footer', diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 334eb49a7c11..ad4ba8d42566 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -787,7 +787,15 @@ class Invoice extends EntityModel implements BalanceAffecting public function canBePaid() { - return ! $this->isPaid() && ! $this->is_deleted && $this->isStandard(); + // already paid or deleted + if ($this->isPaid() || $this->is_deleted) return false; + + // if quote approve is required, them only standard invoices can be paid + if ($this->account->require_approve_quote) { + return $this->isStandard(); + } + + return true; } public static function calcStatusLabel($status, $class, $entityType, $quoteInvoiceId) diff --git a/database/migrations/2019_04_29_073828_add_require_approve_quote.php b/database/migrations/2019_04_29_073828_add_require_approve_quote.php new file mode 100644 index 000000000000..8a728bde4034 --- /dev/null +++ b/database/migrations/2019_04_29_073828_add_require_approve_quote.php @@ -0,0 +1,32 @@ +boolean('require_approve_quote')->default(1); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('accounts', function ($table) { + $table->dropColumn('require_approve_quote'); + }); + } +} diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 4842af52adc8..f223fc96cc7c 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -2842,6 +2842,8 @@ $LANG = array( 'auto_archive_invoice_help' => 'Automatically archive invoices when they are paid.', 'auto_archive_quote' => 'Auto Archive', 'auto_archive_quote_help' => 'Automatically archive quotes when they are converted.', + 'require_approve_quote' => 'Require approve quote', + 'require_approve_quote_help' => 'Require clients to approve quotes.', 'allow_approve_expired_quote' => 'Allow approve expired quote', 'allow_approve_expired_quote_help' => 'Allow clients to approve expired quotes.', 'invoice_workflow' => 'Invoice Workflow', diff --git a/resources/views/accounts/invoice_settings.blade.php b/resources/views/accounts/invoice_settings.blade.php index e79e4a325a15..72cd1229c4d2 100644 --- a/resources/views/accounts/invoice_settings.blade.php +++ b/resources/views/accounts/invoice_settings.blade.php @@ -415,6 +415,11 @@ ->blockHelp(trans('texts.auto_archive_quote_help')) ->value(1) !!} + {!! Former::checkbox('require_approve_quote') + ->text(trans('texts.enable')) + ->blockHelp(trans('texts.require_approve_quote')) + ->value(1) !!} + {!! Former::checkbox('allow_approve_expired_quote') ->text(trans('texts.enable')) ->blockHelp(trans('texts.allow_approve_expired_quote_help')) diff --git a/resources/views/invoices/view.blade.php b/resources/views/invoices/view.blade.php index d7652eb21d83..fb026a746f47 100644 --- a/resources/views/invoices/view.blade.php +++ b/resources/views/invoices/view.blade.php @@ -160,7 +160,7 @@ @include($partialView) @else
- @if ($invoice->isQuote()) + @if ($invoice->isQuote() && $approveRequired) {!! Button::normal(trans('texts.download'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}   @if ($showApprove) {!! Button::success(trans('texts.approve'))->withAttributes(['id' => 'approveButton', 'onclick' => 'onApproveClick()', 'class' => 'require-authorization'])->large() !!} From d7368851f5edf4218b7aea9ba00d7447af8f5d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristia=CC=81n=20Feldsam?= Date: Mon, 29 Apr 2019 10:59:24 +0200 Subject: [PATCH 2/5] PaymentDriver - Convert quote to invoice on payment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristián Feldsam --- app/Ninja/PaymentDrivers/BasePaymentDriver.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/Ninja/PaymentDrivers/BasePaymentDriver.php b/app/Ninja/PaymentDrivers/BasePaymentDriver.php index 9e672a56fbc0..8103b4f7010a 100644 --- a/app/Ninja/PaymentDrivers/BasePaymentDriver.php +++ b/app/Ninja/PaymentDrivers/BasePaymentDriver.php @@ -698,6 +698,13 @@ class BasePaymentDriver if (! $invoice->canBePaid()) { return false; } + + // check if invoice is quote and if is, them convert it + if($invoice->isQuote()) { + $invoiceService = app('App\Services\InvoiceService'); + $invoice = $invoiceService->convertQuote($invoice); + } + $invoice->markSentIfUnsent(); $payment = Payment::createNew($invitation); From 90d132ad20fe89ce4ceb415205203ecd0bc3186e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristia=CC=81n=20Feldsam?= Date: Mon, 29 Apr 2019 12:06:38 +0200 Subject: [PATCH 3/5] BasePaymentDriver - Convert Quote - Fix Invitation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristián Feldsam --- app/Models/Invoice.php | 14 ++++++++++++++ app/Ninja/PaymentDrivers/BasePaymentDriver.php | 1 + 2 files changed, 15 insertions(+) diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index ad4ba8d42566..9e5e1c55c8b0 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -542,6 +542,20 @@ class Invoice extends EntityModel implements BalanceAffecting }); } + /** + * @return Invitation|null + */ + public function invitationByContactId(int $contactId) + { + foreach ($this->invitations as $invitation) { + if ($invitation->contact_id === $contactId) { + return $invitation; + } + } + + return null; + } + /** * @param $typeId * diff --git a/app/Ninja/PaymentDrivers/BasePaymentDriver.php b/app/Ninja/PaymentDrivers/BasePaymentDriver.php index 8103b4f7010a..9bbc232decd5 100644 --- a/app/Ninja/PaymentDrivers/BasePaymentDriver.php +++ b/app/Ninja/PaymentDrivers/BasePaymentDriver.php @@ -703,6 +703,7 @@ class BasePaymentDriver if($invoice->isQuote()) { $invoiceService = app('App\Services\InvoiceService'); $invoice = $invoiceService->convertQuote($invoice); + $invitation = $invoice->invitationByContactId($invitation->contact_id); } $invoice->markSentIfUnsent(); From 7f304028e6c34d1a2073fedc7a2c42f0e6fd70cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristia=CC=81n=20Feldsam?= Date: Mon, 29 Apr 2019 12:51:07 +0200 Subject: [PATCH 4/5] View Quote - Approve not required - Show link to Invoice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristián Feldsam --- resources/views/invoices/view.blade.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/resources/views/invoices/view.blade.php b/resources/views/invoices/view.blade.php index fb026a746f47..b196834d3247 100644 --- a/resources/views/invoices/view.blade.php +++ b/resources/views/invoices/view.blade.php @@ -167,6 +167,9 @@ @elseif ($invoiceLink = $invoice->getInvoiceLinkForQuote($contact->id)) {!! Button::success(trans('texts.view_invoice'))->asLinkTo($invoiceLink)->large() !!} @endif + @elseif ($invoice->isQuote() && $invoiceLink = $invoice->getInvoiceLinkForQuote($contact->id)) + {!! Button::normal(trans('texts.download'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!} + {!! Button::success(trans('texts.view_invoice'))->asLinkTo($invoiceLink)->large() !!} @elseif ( ! $invoice->canBePaid()) {!! Button::normal(trans('texts.download'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!} @elseif ($invoice->client->account->isGatewayConfigured() && floatval($invoice->balance) && !$invoice->is_recurring) From 98ab5599e5371c3b2c584a1aaeaeaf7309a7078c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristia=CC=81n=20Feldsam?= Date: Mon, 29 Apr 2019 13:50:54 +0200 Subject: [PATCH 5/5] Quote workflow settings enhancements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristián Feldsam --- .../views/accounts/invoice_settings.blade.php | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/resources/views/accounts/invoice_settings.blade.php b/resources/views/accounts/invoice_settings.blade.php index 72cd1229c4d2..9148a94ab537 100644 --- a/resources/views/accounts/invoice_settings.blade.php +++ b/resources/views/accounts/invoice_settings.blade.php @@ -405,11 +405,6 @@
- {!! Former::checkbox('auto_convert_quote') - ->text(trans('texts.enable')) - ->blockHelp(trans('texts.auto_convert_quote_help')) - ->value(1) !!} - {!! Former::checkbox('auto_archive_quote') ->text(trans('texts.enable')) ->blockHelp(trans('texts.auto_archive_quote_help')) @@ -417,7 +412,12 @@ {!! Former::checkbox('require_approve_quote') ->text(trans('texts.enable')) - ->blockHelp(trans('texts.require_approve_quote')) + ->blockHelp(trans('texts.require_approve_quote_help')) + ->value(1) !!} + + {!! Former::checkbox('auto_convert_quote') + ->text(trans('texts.enable')) + ->blockHelp(trans('texts.auto_convert_quote_help')) ->value(1) !!} {!! Former::checkbox('allow_approve_expired_quote') @@ -636,6 +636,7 @@ onClientNumberEnabled(); onCreditNumberEnabled(); onResetFrequencyChange(); + updateCheckboxes(); $('#reset_counter_date').datepicker('update', '{{ Utils::fromSqlDate($account->reset_counter_date) ?: 'new Date()' }}'); $('.reset_counter_date_group .input-group-addon').click(function() { @@ -647,6 +648,14 @@ @endif }); + $('#require_approve_quote').change(updateCheckboxes); + + function updateCheckboxes() { + var checked = $('#require_approve_quote').is(':checked'); + $('#auto_convert_quote').prop('disabled', ! checked); + $('#allow_approve_expired_quote').prop('disabled', ! checked); + } +