mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-07 15:54:31 -04:00
Support paying draft invoices
This commit is contained in:
parent
2da91729b3
commit
eebe61b4d0
@ -9,7 +9,6 @@ use Cache;
|
||||
use Redirect;
|
||||
use DB;
|
||||
use URL;
|
||||
use DropdownButton;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Client;
|
||||
use App\Models\Account;
|
||||
@ -123,46 +122,6 @@ class InvoiceController extends BaseController
|
||||
'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;
|
||||
|
||||
if(!Auth::user()->hasPermission('view_all')){
|
||||
@ -180,7 +139,6 @@ class InvoiceController extends BaseController
|
||||
'title' => trans("texts.edit_{$entityType}"),
|
||||
'client' => $invoice->client,
|
||||
'isRecurring' => $invoice->is_recurring,
|
||||
'actions' => $actions,
|
||||
'lastSent' => $lastSent];
|
||||
$data = array_merge($data, self::getViewModel($invoice));
|
||||
|
||||
|
@ -108,6 +108,9 @@ class PaymentApiController extends BaseAPIController
|
||||
*/
|
||||
public function store(CreatePaymentAPIRequest $request)
|
||||
{
|
||||
// check payment has been marked sent
|
||||
$request->invoice->markSentIfUnsent();
|
||||
|
||||
$payment = $this->paymentRepo->save($request->input());
|
||||
|
||||
if (Input::get('email_receipt')) {
|
||||
|
@ -85,7 +85,6 @@ class PaymentController extends BaseController
|
||||
{
|
||||
$invoices = Invoice::scope()
|
||||
->invoices()
|
||||
->whereIsPublic(true)
|
||||
->where('invoices.balance', '>', 0)
|
||||
->with('client', 'invoice_status')
|
||||
->orderBy('invoice_number')->get();
|
||||
|
@ -33,9 +33,8 @@ class CreatePaymentAPIRequest extends PaymentRequest
|
||||
];
|
||||
}
|
||||
|
||||
$invoice = Invoice::scope($this->invoice_id)
|
||||
$this->invoice = $invoice = Invoice::scope($this->invoice_id)
|
||||
->invoices()
|
||||
->whereIsPublic(true)
|
||||
->firstOrFail();
|
||||
|
||||
$this->merge([
|
||||
|
@ -426,6 +426,25 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
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
|
||||
*/
|
||||
@ -462,7 +481,7 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
*/
|
||||
public function markInvitationSent($invitation, $messageId = false, $notify = true, $notes = false)
|
||||
{
|
||||
if (!$this->isSent()) {
|
||||
if ( ! $this->isSent()) {
|
||||
$this->invoice_status_id = INVOICE_STATUS_SENT;
|
||||
$this->save();
|
||||
}
|
||||
@ -667,7 +686,7 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
*/
|
||||
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');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use stdClass;
|
||||
use Utils;
|
||||
use DropdownButton;
|
||||
use App\Libraries\Skype\InvoiceCard;
|
||||
|
||||
class InvoicePresenter extends EntityPresenter {
|
||||
@ -162,4 +163,50 @@ class InvoicePresenter extends EntityPresenter {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -761,14 +761,7 @@ class InvoiceRepository extends BaseRepository
|
||||
*/
|
||||
public function markSent(Invoice $invoice)
|
||||
{
|
||||
if ( ! $invoice->isSent()) {
|
||||
$invoice->invoice_status_id = INVOICE_STATUS_SENT;
|
||||
}
|
||||
|
||||
$invoice->is_public = true;
|
||||
$invoice->save();
|
||||
|
||||
$invoice->markInvitationsSent();
|
||||
$invoice->markSent();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,7 +199,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
});
|
||||
|
||||
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']);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -564,7 +564,7 @@
|
||||
@if (!$invoice->trashed())
|
||||
@if ($invoice->id)
|
||||
{!! DropdownButton::normal(trans('texts.more_actions'))
|
||||
->withContents($actions)
|
||||
->withContents($invoice->present()->moreActions())
|
||||
->dropup() !!}
|
||||
@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')) !!}
|
||||
|
Loading…
x
Reference in New Issue
Block a user