Support paying draft invoices

This commit is contained in:
Hillel Coren 2017-01-13 09:02:22 +02:00
parent 2da91729b3
commit eebe61b4d0
9 changed files with 76 additions and 58 deletions

View File

@ -9,7 +9,6 @@ use Cache;
use Redirect; use Redirect;
use DB; use DB;
use URL; use URL;
use DropdownButton;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Client; use App\Models\Client;
use App\Models\Account; use App\Models\Account;
@ -123,46 +122,6 @@ class InvoiceController extends BaseController
'invoice_settings' => Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS), 'invoice_settings' => Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS),
]; ];
$actions = [
['url' => 'javascript:onCloneClick()', 'label' => trans("texts.clone_{$entityType}")],
['url' => URL::to("{$entityType}s/{$entityType}_history/{$invoice->public_id}"), 'label' => trans('texts.view_history')],
DropdownButton::DIVIDER
];
if ($entityType == ENTITY_QUOTE) {
if ($invoice->quote_invoice_id) {
$actions[] = ['url' => URL::to("invoices/{$invoice->quote_invoice_id}/edit"), 'label' => trans('texts.view_invoice')];
} else {
$actions[] = ['url' => 'javascript:onConvertClick()', 'label' => trans('texts.convert_to_invoice')];
}
} elseif ($entityType == ENTITY_INVOICE) {
if ($invoice->quote_id) {
$actions[] = ['url' => URL::to("quotes/{$invoice->quote_id}/edit"), 'label' => trans('texts.view_quote')];
}
if (!$invoice->is_recurring && $invoice->balance > 0) {
$actions[] = ['url' => 'javascript:submitBulkAction("markPaid")', 'label' => trans('texts.mark_paid')];
if ($invoice->is_public) {
$actions[] = ['url' => 'javascript:onPaymentClick()', 'label' => trans('texts.enter_payment')];
}
}
foreach ($invoice->payments as $payment) {
$label = trans('texts.view_payment');
if (count($invoice->payments) > 1) {
$label .= ' - ' . $account->formatMoney($payment->amount, $invoice->client);
}
$actions[] = ['url' => $payment->present()->url, 'label' => $label];
}
}
if (count($actions) > 3) {
$actions[] = DropdownButton::DIVIDER;
}
$actions[] = ['url' => 'javascript:onArchiveClick()', 'label' => trans("texts.archive_{$entityType}")];
$actions[] = ['url' => 'javascript:onDeleteClick()', 'label' => trans("texts.delete_{$entityType}")];
$lastSent = ($invoice->is_recurring && $invoice->last_sent_date) ? $invoice->recurring_invoices->last() : null; $lastSent = ($invoice->is_recurring && $invoice->last_sent_date) ? $invoice->recurring_invoices->last() : null;
if(!Auth::user()->hasPermission('view_all')){ if(!Auth::user()->hasPermission('view_all')){
@ -180,7 +139,6 @@ class InvoiceController extends BaseController
'title' => trans("texts.edit_{$entityType}"), 'title' => trans("texts.edit_{$entityType}"),
'client' => $invoice->client, 'client' => $invoice->client,
'isRecurring' => $invoice->is_recurring, 'isRecurring' => $invoice->is_recurring,
'actions' => $actions,
'lastSent' => $lastSent]; 'lastSent' => $lastSent];
$data = array_merge($data, self::getViewModel($invoice)); $data = array_merge($data, self::getViewModel($invoice));

View File

@ -108,6 +108,9 @@ class PaymentApiController extends BaseAPIController
*/ */
public function store(CreatePaymentAPIRequest $request) public function store(CreatePaymentAPIRequest $request)
{ {
// check payment has been marked sent
$request->invoice->markSentIfUnsent();
$payment = $this->paymentRepo->save($request->input()); $payment = $this->paymentRepo->save($request->input());
if (Input::get('email_receipt')) { if (Input::get('email_receipt')) {
@ -142,7 +145,7 @@ class PaymentApiController extends BaseAPIController
public function destroy(UpdatePaymentRequest $request) public function destroy(UpdatePaymentRequest $request)
{ {
$payment = $request->entity(); $payment = $request->entity();
$this->clientRepo->delete($payment); $this->clientRepo->delete($payment);
return $this->itemResponse($payment); return $this->itemResponse($payment);

View File

@ -85,7 +85,6 @@ class PaymentController extends BaseController
{ {
$invoices = Invoice::scope() $invoices = Invoice::scope()
->invoices() ->invoices()
->whereIsPublic(true)
->where('invoices.balance', '>', 0) ->where('invoices.balance', '>', 0)
->with('client', 'invoice_status') ->with('client', 'invoice_status')
->orderBy('invoice_number')->get(); ->orderBy('invoice_number')->get();

View File

@ -33,9 +33,8 @@ class CreatePaymentAPIRequest extends PaymentRequest
]; ];
} }
$invoice = Invoice::scope($this->invoice_id) $this->invoice = $invoice = Invoice::scope($this->invoice_id)
->invoices() ->invoices()
->whereIsPublic(true)
->firstOrFail(); ->firstOrFail();
$this->merge([ $this->merge([

View File

@ -426,6 +426,25 @@ class Invoice extends EntityModel implements BalanceAffecting
return $this->isType(INVOICE_TYPE_STANDARD) && ! $this->is_recurring; return $this->isType(INVOICE_TYPE_STANDARD) && ! $this->is_recurring;
} }
public function markSentIfUnsent()
{
if ( ! $this->isSent()) {
$this->markSent();
}
}
public function markSent()
{
if ( ! $this->isSent()) {
$this->invoice_status_id = INVOICE_STATUS_SENT;
}
$this->is_public = true;
$this->save();
$this->markInvitationsSent();
}
/** /**
* @param bool $notify * @param bool $notify
*/ */
@ -462,7 +481,7 @@ class Invoice extends EntityModel implements BalanceAffecting
*/ */
public function markInvitationSent($invitation, $messageId = false, $notify = true, $notes = false) public function markInvitationSent($invitation, $messageId = false, $notify = true, $notes = false)
{ {
if (!$this->isSent()) { if ( ! $this->isSent()) {
$this->invoice_status_id = INVOICE_STATUS_SENT; $this->invoice_status_id = INVOICE_STATUS_SENT;
$this->save(); $this->save();
} }
@ -667,7 +686,7 @@ class Invoice extends EntityModel implements BalanceAffecting
*/ */
public function isSent() public function isSent()
{ {
return $this->invoice_status_id >= INVOICE_STATUS_SENT && $this->is_public; return $this->invoice_status_id >= INVOICE_STATUS_SENT && $this->getOriginal('is_public');
} }
/** /**

View File

@ -2,6 +2,7 @@
use stdClass; use stdClass;
use Utils; use Utils;
use DropdownButton;
use App\Libraries\Skype\InvoiceCard; use App\Libraries\Skype\InvoiceCard;
class InvoicePresenter extends EntityPresenter { class InvoicePresenter extends EntityPresenter {
@ -162,4 +163,50 @@ class InvoicePresenter extends EntityPresenter {
return [$data]; return [$data];
} }
public function moreActions()
{
$invoice = $this->entity;
$entityType = $invoice->getEntityType();
$actions = [
['url' => 'javascript:onCloneClick()', 'label' => trans("texts.clone_{$entityType}")],
['url' => url("{$entityType}s/{$entityType}_history/{$invoice->public_id}"), 'label' => trans('texts.view_history')],
DropdownButton::DIVIDER
];
if ($entityType == ENTITY_QUOTE) {
if ($invoice->quote_invoice_id) {
$actions[] = ['url' => url("invoices/{$invoice->quote_invoice_id}/edit"), 'label' => trans('texts.view_invoice')];
} else {
$actions[] = ['url' => 'javascript:onConvertClick()', 'label' => trans('texts.convert_to_invoice')];
}
} elseif ($entityType == ENTITY_INVOICE) {
if ($invoice->quote_id) {
$actions[] = ['url' => url("quotes/{$invoice->quote_id}/edit"), 'label' => trans('texts.view_quote')];
}
if (!$invoice->is_recurring && $invoice->balance > 0) {
$actions[] = ['url' => 'javascript:submitBulkAction("markPaid")', 'label' => trans('texts.mark_paid')];
$actions[] = ['url' => 'javascript:onPaymentClick()', 'label' => trans('texts.enter_payment')];
}
foreach ($invoice->payments as $payment) {
$label = trans('texts.view_payment');
if (count($invoice->payments) > 1) {
$label .= ' - ' . $invoice->account->formatMoney($payment->amount, $invoice->client);
}
$actions[] = ['url' => $payment->present()->url, 'label' => $label];
}
}
if (count($actions) > 3) {
$actions[] = DropdownButton::DIVIDER;
}
$actions[] = ['url' => 'javascript:onArchiveClick()', 'label' => trans("texts.archive_{$entityType}")];
$actions[] = ['url' => 'javascript:onDeleteClick()', 'label' => trans("texts.delete_{$entityType}")];
return $actions;
}
} }

View File

@ -761,14 +761,7 @@ class InvoiceRepository extends BaseRepository
*/ */
public function markSent(Invoice $invoice) public function markSent(Invoice $invoice)
{ {
if ( ! $invoice->isSent()) { $invoice->markSent();
$invoice->invoice_status_id = INVOICE_STATUS_SENT;
}
$invoice->is_public = true;
$invoice->save();
$invoice->markInvitationsSent();
} }
/** /**

View File

@ -199,7 +199,7 @@ class AppServiceProvider extends ServiceProvider
}); });
Validator::extend('valid_subdomain', function($attribute, $value, $parameters) { Validator::extend('valid_subdomain', function($attribute, $value, $parameters) {
return ! in_array($value, ['www', 'app','mail', 'admin', 'blog', 'user', 'contact', 'payment', 'payments', 'billing', 'invoice', 'business', 'owner', 'info', 'ninja', 'docs', 'doc', 'documents']); return ! in_array($value, ['www', 'app', 'mail', 'admin', 'blog', 'user', 'contact', 'payment', 'payments', 'billing', 'invoice', 'business', 'owner', 'info', 'ninja', 'docs', 'doc', 'documents', 'download']);
}); });
} }

View File

@ -564,7 +564,7 @@
@if (!$invoice->trashed()) @if (!$invoice->trashed())
@if ($invoice->id) @if ($invoice->id)
{!! DropdownButton::normal(trans('texts.more_actions')) {!! DropdownButton::normal(trans('texts.more_actions'))
->withContents($actions) ->withContents($invoice->present()->moreActions())
->dropup() !!} ->dropup() !!}
@elseif ( ! $invoice->isQuote() && Request::is('*/clone')) @elseif ( ! $invoice->isQuote() && Request::is('*/clone'))
{!! Button::normal(trans($invoice->is_recurring ? 'texts.disable_recurring' : 'texts.enable_recurring'))->withAttributes(['id' => 'recurrButton', 'onclick' => 'onRecurrClick()'])->appendIcon(Icon::create('repeat')) !!} {!! Button::normal(trans($invoice->is_recurring ? 'texts.disable_recurring' : 'texts.enable_recurring'))->withAttributes(['id' => 'recurrButton', 'onclick' => 'onRecurrClick()'])->appendIcon(Icon::create('repeat')) !!}