diff --git a/CHANGELOG.md b/CHANGELOG.md index 51614a3ba36e..48d1dd766c90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Release notes ## [Unreleased (daily channel)](https://github.com/invoiceninja/invoiceninja/tree/v5-develop) +## Added: +- Client portal: Show message when trying to approve non-approvable quotes +- Client portal: Remove "Approve" button from single quote page if quote is non-approvable + +## Fixed: +- Client portal: Showing message instead of blank page when trying to download zero quotes. ## [v5.2.0-release](https://github.com/invoiceninja/invoiceninja/releases/tag/v5.2.0-release) ## Added: diff --git a/app/Http/Controllers/ClientPortal/QuoteController.php b/app/Http/Controllers/ClientPortal/QuoteController.php index 6add1d63bc61..39f2d5444da0 100644 --- a/app/Http/Controllers/ClientPortal/QuoteController.php +++ b/app/Http/Controllers/ClientPortal/QuoteController.php @@ -85,7 +85,9 @@ class QuoteController extends Controller ->get(); if (! $quotes || $quotes->count() == 0) { - return; + return redirect() + ->route('client.quotes.index') + ->with('message', ctrans('texts.no_quotes_available_for_download')); } if ($quotes->count() == 1) { @@ -121,7 +123,9 @@ class QuoteController extends Controller ->get(); if (!$quotes || $quotes->count() == 0) { - return redirect()->route('client.quotes.index'); + return redirect() + ->route('client.quotes.index') + ->with('message', ctrans('texts.quotes_with_status_sent_can_be_approved')); } if ($process) { diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index f66c381439f3..d9e3f3493455 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -4278,6 +4278,8 @@ $LANG = array( 'one_time_purchases' => 'One time purchases', 'recurring_purchases' => 'Recurring purchases', 'you_might_be_interested_in_following' => 'You might be interested in following', + 'quotes_with_status_sent_can_be_approved' => 'Only quotes with "Sent" status can be approved.', + 'no_quotes_available_for_download' => 'No quotes available for download.', ); return $LANG; diff --git a/resources/views/portal/ninja2020/quotes/show.blade.php b/resources/views/portal/ninja2020/quotes/show.blade.php index 380242d429f5..46ddef487cad 100644 --- a/resources/views/portal/ninja2020/quotes/show.blade.php +++ b/resources/views/portal/ninja2020/quotes/show.blade.php @@ -19,10 +19,12 @@ @endcomponent @endif - @if(!$quote->isApproved()) + @if($quote->status_id === \App\Models\Quote::STATUS_SENT)
@include('portal.ninja2020.quotes.includes.actions', ['quote' => $quote])
+ @else +

{{ ctrans('texts.quotes_with_status_sent_can_be_approved') }}

@endif @include('portal.ninja2020.components.entity-documents', ['entity' => $quote]) diff --git a/tests/Browser/ClientPortal/QuotesTest.php b/tests/Browser/ClientPortal/QuotesTest.php index 2a294eca2ed2..b05c8992f506 100644 --- a/tests/Browser/ClientPortal/QuotesTest.php +++ b/tests/Browser/ClientPortal/QuotesTest.php @@ -70,6 +70,17 @@ class QuotesTest extends DuskTestCase } public function testQuotesWithSentStatusCanOnlyBeApproved() + { + $this->browse(function (Browser $browser) { + $browser + ->visitRoute('client.quotes.index') + ->clickLink('View') + ->assertSee('Only quotes with "Sent" status can be approved.') + ->visitRoute('client.logout'); + }); + } + + public function testMessageForNonApprovableQuotesIsVisible() { $this->browse(function (Browser $browser) { $browser @@ -78,7 +89,18 @@ class QuotesTest extends DuskTestCase ->press('Approve') ->assertPathIs('/client/quotes') ->assertDontSee('Quote(s) approved successfully.') + ->assertSee('Only quotes with "Sent" status can be approved.') ->visitRoute('client.logout'); }); } + + public function testNoQuotesAvailableForDownloadMessage() + { + $this->browse(function (Browser $browser) { + $browser + ->visitRoute('client.quotes.index') + ->press('Download') + ->assertSee('No quotes available for download.'); + }); + } }