diff --git a/app/Http/Controllers/ProposalController.php b/app/Http/Controllers/ProposalController.php index 96dd3861ca12..5fbf11bddf3c 100644 --- a/app/Http/Controllers/ProposalController.php +++ b/app/Http/Controllers/ProposalController.php @@ -62,7 +62,7 @@ class ProposalController extends BaseController 'title' => trans('texts.new_proposal'), 'invoices' => Invoice::scope()->with('client.contacts')->unapprovedQuotes()->orderBy('id')->get(), 'templates' => ProposalTemplate::whereAccountId($account->id)->orWhereNull('account_id')->orderBy('name')->get(), - 'invoicePublicId' => $request->invoicee_id, + 'invoicePublicId' => $request->invoice_id, ]; return View::make('proposals.edit', $data); diff --git a/app/Http/Requests/ProposalSnippetRequest.php b/app/Http/Requests/ProposalSnippetRequest.php index e02b4caa6d26..4892dade0045 100644 --- a/app/Http/Requests/ProposalSnippetRequest.php +++ b/app/Http/Requests/ProposalSnippetRequest.php @@ -2,7 +2,33 @@ namespace App\Http\Requests; +use App\Models\ProposalCategory; + class ProposalSnippetRequest extends EntityRequest { protected $entityType = ENTITY_PROPOSAL_SNIPPET; + + public function sanitize() + { + $input = $this->all(); + + // check if we're creating a new proposal category + if ($this->proposal_category_id == '-1') { + $data = [ + 'name' => trim($this->proposal_category_name) + ]; + if (ProposalCategory::validate($data) === true) { + $category = app('App\Ninja\Repositories\ProposalCategoryRepository')->save($data); + $input['proposal_category_id'] = $category->id; + } else { + $input['proposal_category_id'] = null; + } + } elseif ($this->proposal_category_id) { + $input['proposal_category_id'] = ProposalCategory::getPrivateId($this->proposal_category_id); + } + + $this->replace($input); + + return $this->all(); + } } diff --git a/app/Ninja/Datatables/InvoiceDatatable.php b/app/Ninja/Datatables/InvoiceDatatable.php index 801fb52a97f9..5a59eda7b02f 100644 --- a/app/Ninja/Datatables/InvoiceDatatable.php +++ b/app/Ninja/Datatables/InvoiceDatatable.php @@ -137,7 +137,7 @@ class InvoiceDatatable extends EntityDatatable return "javascript:submitForm_{$entityType}('markSent', {$model->public_id})"; }, function ($model) { - return $model->invoice_status_id < INVOICE_STATUS_SENT && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); + return ! $model->is_public && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); }, ], [ @@ -167,6 +167,15 @@ class InvoiceDatatable extends EntityDatatable return $entityType == ENTITY_QUOTE && $model->quote_invoice_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]); }, ], + [ + trans('texts.new_proposal'), + function ($model) { + return URL::to("proposals/create/{$model->public_id}"); + }, + function ($model) use ($entityType) { + return $entityType == ENTITY_QUOTE && ! $model->quote_invoice_id && $model->invoice_status_id < INVOICE_STATUS_APPROVED && Auth::user()->can('create', ENTITY_PROPOSAL); + }, + ], [ trans('texts.convert_to_invoice'), function ($model) { diff --git a/app/Ninja/Presenters/InvoicePresenter.php b/app/Ninja/Presenters/InvoicePresenter.php index 99236c88c24a..e3c0177c7729 100644 --- a/app/Ninja/Presenters/InvoicePresenter.php +++ b/app/Ninja/Presenters/InvoicePresenter.php @@ -261,6 +261,9 @@ class InvoicePresenter extends EntityPresenter if ($invoice->quote_invoice_id) { $actions[] = ['url' => url("invoices/{$invoice->quote_invoice_id}/edit"), 'label' => trans('texts.view_invoice')]; } else { + if (! $invoice->isApproved()) { + $actions[] = ['url' => url("proposals/create/{$invoice->public_id}"), 'label' => trans('texts.new_proposal')]; + } $actions[] = ['url' => 'javascript:onConvertClick()', 'label' => trans('texts.convert_to_invoice')]; } } elseif ($entityType == ENTITY_INVOICE) { diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 07f01954830c..5915ceb0889a 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -2726,6 +2726,7 @@ $LANG = array( 'standard' => 'Standard', 'icon' => 'Icon', 'proposal_not_found' => 'The requested proposal is not available', + 'create_proposal_category' => 'Create category', ); diff --git a/resources/views/proposals/snippets/edit.blade.php b/resources/views/proposals/snippets/edit.blade.php index af232dd046d5..11ffbe3a0a62 100644 --- a/resources/views/proposals/snippets/edit.blade.php +++ b/resources/views/proposals/snippets/edit.blade.php @@ -80,6 +80,9 @@ $(function() { var categoryId = {{ $categoryPublicId ?: 0 }}; var $proposal_categorySelect = $('select#proposal_category_id'); + @if (Auth::user()->can('create', ENTITY_PROPOSAL_CATEGORY)) + $proposal_categorySelect.append(new Option("{{ trans('texts.create_proposal_category') }}: $name", '-1')); + @endif for (var i = 0; i < categories.length; i++) { var category = categories[i]; categoryMap[category.public_id] = category; diff --git a/routes/web.php b/routes/web.php index d05eb834d5ef..42d9090f6bc1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -226,7 +226,7 @@ Route::group(['middleware' => ['lookup:user', 'auth:user']], function () { Route::post('proposals/proposals/bulk', 'ProposalController@bulk'); Route::get('proposals/{proposals}/edit', 'ProposalController@edit'); - Route::get('proposals/create/{quote_id?}', 'ProposalController@create'); + Route::get('proposals/create/{invoice_id?}', 'ProposalController@create'); Route::resource('proposals', 'ProposalController'); Route::get('api/proposals', 'ProposalController@getDatatable');