Merge pull request #2807 from FELDSAM-INC/feature/require-quote-approve-option

Feature/require quote approve option
This commit is contained in:
Hillel Coren 2019-04-29 19:46:19 +03:00 committed by GitHub
commit e14e27cac6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 93 additions and 8 deletions

View File

@ -1065,6 +1065,7 @@ class AccountController extends BaseController
$account->quote_terms = Input::get('quote_terms'); $account->quote_terms = Input::get('quote_terms');
$account->auto_convert_quote = Input::get('auto_convert_quote'); $account->auto_convert_quote = Input::get('auto_convert_quote');
$account->auto_archive_quote = Input::get('auto_archive_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->allow_approve_expired_quote = Input::get('allow_approve_expired_quote');
$account->auto_archive_invoice = Input::get('auto_archive_invoice'); $account->auto_archive_invoice = Input::get('auto_archive_invoice');
$account->auto_email_invoice = Input::get('auto_email_invoice'); $account->auto_email_invoice = Input::get('auto_email_invoice');

View File

@ -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) { if ($invoice->invoice_status_id >= INVOICE_STATUS_APPROVED) {
$showApprove = false; $showApprove = false;
} }
$data += [ $data += [
'account' => $account, 'account' => $account,
'approveRequired' => $account->require_approve_quote,
'showApprove' => $showApprove, 'showApprove' => $showApprove,
'showBreadcrumbs' => false, 'showBreadcrumbs' => false,
'invoice' => $invoice->hidePrivateFields(), 'invoice' => $invoice->hidePrivateFields(),

View File

@ -109,6 +109,8 @@ class Account extends Eloquent
'body_font_id', 'body_font_id',
'auto_convert_quote', 'auto_convert_quote',
'auto_archive_quote', 'auto_archive_quote',
'require_approve_quote',
'allow_approve_expired_quote',
'auto_archive_invoice', 'auto_archive_invoice',
'auto_email_invoice', 'auto_email_invoice',
'all_pages_footer', 'all_pages_footer',

View File

@ -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 * @param $typeId
* *
@ -787,7 +801,15 @@ class Invoice extends EntityModel implements BalanceAffecting
public function canBePaid() 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) public static function calcStatusLabel($status, $class, $entityType, $quoteInvoiceId)

View File

@ -698,6 +698,14 @@ class BasePaymentDriver
if (! $invoice->canBePaid()) { if (! $invoice->canBePaid()) {
return false; 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);
$invitation = $invoice->invitationByContactId($invitation->contact_id);
}
$invoice->markSentIfUnsent(); $invoice->markSentIfUnsent();
$payment = Payment::createNew($invitation); $payment = Payment::createNew($invitation);

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddRequireApproveQuote extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('accounts', function ($table) {
$table->boolean('require_approve_quote')->default(1);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('accounts', function ($table) {
$table->dropColumn('require_approve_quote');
});
}
}

View File

@ -2842,6 +2842,8 @@ $LANG = array(
'auto_archive_invoice_help' => 'Automatically archive invoices when they are paid.', 'auto_archive_invoice_help' => 'Automatically archive invoices when they are paid.',
'auto_archive_quote' => 'Auto Archive', 'auto_archive_quote' => 'Auto Archive',
'auto_archive_quote_help' => 'Automatically archive quotes when they are converted.', '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' => 'Allow approve expired quote',
'allow_approve_expired_quote_help' => 'Allow clients to approve expired quotes.', 'allow_approve_expired_quote_help' => 'Allow clients to approve expired quotes.',
'invoice_workflow' => 'Invoice Workflow', 'invoice_workflow' => 'Invoice Workflow',

View File

@ -405,16 +405,21 @@
</div> </div>
<div role="tabpanel" class="tab-pane" id="quote_workflow"> <div role="tabpanel" class="tab-pane" id="quote_workflow">
<div class="panel-body"> <div class="panel-body">
{!! Former::checkbox('auto_convert_quote')
->text(trans('texts.enable'))
->blockHelp(trans('texts.auto_convert_quote_help'))
->value(1) !!}
{!! Former::checkbox('auto_archive_quote') {!! Former::checkbox('auto_archive_quote')
->text(trans('texts.enable')) ->text(trans('texts.enable'))
->blockHelp(trans('texts.auto_archive_quote_help')) ->blockHelp(trans('texts.auto_archive_quote_help'))
->value(1) !!} ->value(1) !!}
{!! Former::checkbox('require_approve_quote')
->text(trans('texts.enable'))
->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') {!! Former::checkbox('allow_approve_expired_quote')
->text(trans('texts.enable')) ->text(trans('texts.enable'))
->blockHelp(trans('texts.allow_approve_expired_quote_help')) ->blockHelp(trans('texts.allow_approve_expired_quote_help'))
@ -631,6 +636,7 @@
onClientNumberEnabled(); onClientNumberEnabled();
onCreditNumberEnabled(); onCreditNumberEnabled();
onResetFrequencyChange(); onResetFrequencyChange();
updateCheckboxes();
$('#reset_counter_date').datepicker('update', '{{ Utils::fromSqlDate($account->reset_counter_date) ?: 'new Date()' }}'); $('#reset_counter_date').datepicker('update', '{{ Utils::fromSqlDate($account->reset_counter_date) ?: 'new Date()' }}');
$('.reset_counter_date_group .input-group-addon').click(function() { $('.reset_counter_date_group .input-group-addon').click(function() {
@ -642,6 +648,14 @@
@endif @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);
}
</script> </script>

View File

@ -160,13 +160,16 @@
@include($partialView) @include($partialView)
@else @else
<div id="paymentButtons" class="pull-right" style="text-align:right"> <div id="paymentButtons" class="pull-right" style="text-align:right">
@if ($invoice->isQuote()) @if ($invoice->isQuote() && $approveRequired)
{!! Button::normal(trans('texts.download'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}&nbsp;&nbsp; {!! Button::normal(trans('texts.download'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}&nbsp;&nbsp;
@if ($showApprove) @if ($showApprove)
{!! Button::success(trans('texts.approve'))->withAttributes(['id' => 'approveButton', 'onclick' => 'onApproveClick()', 'class' => 'require-authorization'])->large() !!} {!! Button::success(trans('texts.approve'))->withAttributes(['id' => 'approveButton', 'onclick' => 'onApproveClick()', 'class' => 'require-authorization'])->large() !!}
@elseif ($invoiceLink = $invoice->getInvoiceLinkForQuote($contact->id)) @elseif ($invoiceLink = $invoice->getInvoiceLinkForQuote($contact->id))
{!! Button::success(trans('texts.view_invoice'))->asLinkTo($invoiceLink)->large() !!} {!! Button::success(trans('texts.view_invoice'))->asLinkTo($invoiceLink)->large() !!}
@endif @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()) @elseif ( ! $invoice->canBePaid())
{!! Button::normal(trans('texts.download'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!} {!! Button::normal(trans('texts.download'))->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}
@elseif ($invoice->client->account->isGatewayConfigured() && floatval($invoice->balance) && !$invoice->is_recurring) @elseif ($invoice->client->account->isGatewayConfigured() && floatval($invoice->balance) && !$invoice->is_recurring)