Hide draft invoices from the client portal

This commit is contained in:
Hillel Coren 2016-12-04 23:26:38 +02:00
parent 9398c45b56
commit 8d8156f580
10 changed files with 58 additions and 22 deletions

View File

@ -99,6 +99,7 @@ class InvoiceController extends BaseController
if ($clone) { if ($clone) {
$invoice->id = $invoice->public_id = null; $invoice->id = $invoice->public_id = null;
$invoice->is_public = false;
$invoice->invoice_number = $account->getNextInvoiceNumber($invoice); $invoice->invoice_number = $account->getNextInvoiceNumber($invoice);
$invoice->balance = $invoice->amount; $invoice->balance = $invoice->amount;
$invoice->invoice_status_id = 0; $invoice->invoice_status_id = 0;
@ -129,10 +130,6 @@ class InvoiceController extends BaseController
DropdownButton::DIVIDER DropdownButton::DIVIDER
]; ];
if ($invoice->invoice_status_id < INVOICE_STATUS_SENT && !$invoice->is_recurring) {
$actions[] = ['url' => 'javascript:onMarkClick()', 'label' => trans('texts.mark_sent')];
}
if ($entityType == ENTITY_QUOTE) { if ($entityType == ENTITY_QUOTE) {
if ($invoice->quote_invoice_id) { if ($invoice->quote_invoice_id) {
$actions[] = ['url' => URL::to("invoices/{$invoice->quote_invoice_id}/edit"), 'label' => trans('texts.view_invoice')]; $actions[] = ['url' => URL::to("invoices/{$invoice->quote_invoice_id}/edit"), 'label' => trans('texts.view_invoice')];
@ -194,7 +191,7 @@ class InvoiceController extends BaseController
} }
// Set the invitation data on the client's contacts // Set the invitation data on the client's contacts
if (!$clone) { if ($invoice->is_public && ! $clone) {
$clients = $data['clients']; $clients = $data['clients'];
foreach ($clients as $client) { foreach ($clients as $client) {
if ($client->id != $invoice->client->id) { if ($client->id != $invoice->client->id) {

View File

@ -97,8 +97,8 @@ class Invitation extends EntityModel
if ($this->$field && $this->field != '0000-00-00 00:00:00') { if ($this->$field && $this->field != '0000-00-00 00:00:00') {
$date = Utils::dateToString($this->$field); $date = Utils::dateToString($this->$field);
$hasValue = true; $hasValue = true;
} $parts[] = trans('texts.invitation_status_' . $status) . ': ' . $date;
$parts[] = trans('texts.invitation_status_' . $status) . ': ' . $date; }
} }
return $hasValue ? implode($parts, '<br/>') : false; return $hasValue ? implode($parts, '<br/>') : false;

View File

@ -153,7 +153,7 @@ class Invoice extends EntityModel implements BalanceAffecting
*/ */
public function affectsBalance() public function affectsBalance()
{ {
return $this->isType(INVOICE_TYPE_STANDARD) && !$this->is_recurring; return $this->isType(INVOICE_TYPE_STANDARD) && !$this->is_recurring && $this->is_public;
} }
/** /**
@ -161,7 +161,7 @@ class Invoice extends EntityModel implements BalanceAffecting
*/ */
public function getAdjustment() public function getAdjustment()
{ {
if (!$this->affectsBalance()) { if ( ! $this->affectsBalance()) {
return 0; return 0;
} }
@ -173,6 +173,11 @@ class Invoice extends EntityModel implements BalanceAffecting
*/ */
private function getRawAdjustment() private function getRawAdjustment()
{ {
// if we've just made the invoice public then apply the full amount
if ($this->is_public && ! $this->getOriginal('is_public')) {
return $this->amount;
}
return floatval($this->amount) - floatval($this->getOriginal('amount')); return floatval($this->amount) - floatval($this->getOriginal('amount'));
} }
@ -410,6 +415,8 @@ class Invoice extends EntityModel implements BalanceAffecting
*/ */
public function markInvitationsSent($notify = false) public function markInvitationsSent($notify = false)
{ {
$this->load('invitations');
foreach ($this->invitations as $invitation) { foreach ($this->invitations as $invitation) {
$this->markInvitationSent($invitation, false, $notify); $this->markInvitationSent($invitation, false, $notify);
} }

View File

@ -190,6 +190,7 @@ class DocumentRepository extends BaseRepository
->where('invoices.is_deleted', '=', false) ->where('invoices.is_deleted', '=', false)
->where('clients.deleted_at', '=', null) ->where('clients.deleted_at', '=', null)
->where('invoices.is_recurring', '=', false) ->where('invoices.is_recurring', '=', false)
->where('invoices.is_public', '=', true)
// TODO: This needs to be a setting to also hide the activity on the dashboard page // TODO: This needs to be a setting to also hide the activity on the dashboard page
//->where('invoices.invoice_status_id', '>=', INVOICE_STATUS_SENT) //->where('invoices.invoice_status_id', '>=', INVOICE_STATUS_SENT)
->select( ->select(

View File

@ -75,7 +75,8 @@ class InvoiceRepository extends BaseRepository
'invoices.deleted_at', 'invoices.deleted_at',
'invoices.is_deleted', 'invoices.is_deleted',
'invoices.partial', 'invoices.partial',
'invoices.user_id' 'invoices.user_id',
'invoices.is_public'
); );
$this->applyFilters($query, $entityType, ENTITY_INVOICE); $this->applyFilters($query, $entityType, ENTITY_INVOICE);
@ -227,6 +228,7 @@ class InvoiceRepository extends BaseRepository
->where('contacts.deleted_at', '=', null) ->where('contacts.deleted_at', '=', null)
->where('contacts.is_primary', '=', true) ->where('contacts.is_primary', '=', true)
->where('invoices.is_recurring', '=', false) ->where('invoices.is_recurring', '=', false)
->where('invoices.is_public', '=', true)
// This needs to be a setting to also hide the activity on the dashboard page // This needs to be a setting to also hide the activity on the dashboard page
//->where('invoices.invoice_status_id', '>=', INVOICE_STATUS_SENT) //->where('invoices.invoice_status_id', '>=', INVOICE_STATUS_SENT)
->select( ->select(
@ -308,6 +310,14 @@ class InvoiceRepository extends BaseRepository
return $invoice; return $invoice;
} }
// set default to true for backwards compatability
if ( ! isset($data['is_public']) || filter_var($data['is_public'], FILTER_VALIDATE_BOOLEAN)) {
$invoice->is_public = true;
if ( ! $invoice->isSent()) {
$invoice->invoice_status_id = INVOICE_STATUS_SENT;
}
}
$invoice->fill($data); $invoice->fill($data);
if ((isset($data['set_default_terms']) && $data['set_default_terms']) if ((isset($data['set_default_terms']) && $data['set_default_terms'])
@ -672,7 +682,8 @@ class InvoiceRepository extends BaseRepository
'custom_taxes2', 'custom_taxes2',
'partial', 'partial',
'custom_text_value1', 'custom_text_value1',
'custom_text_value2', ] as $field) { 'custom_text_value2',
] as $field) {
$clone->$field = $invoice->$field; $clone->$field = $invoice->$field;
} }
@ -731,7 +742,12 @@ class InvoiceRepository extends BaseRepository
*/ */
public function markSent(Invoice $invoice) public function markSent(Invoice $invoice)
{ {
$invoice->markInvitationsSent(); if ( ! $invoice->isSent()) {
$invoice->invoice_status_id = INVOICE_STATUS_SENT;
}
$invoice->is_public = true;
$invoice->save();
} }
/** /**
@ -748,7 +764,7 @@ class InvoiceRepository extends BaseRepository
} }
$invoice = $invitation->invoice; $invoice = $invitation->invoice;
if (!$invoice || $invoice->is_deleted) { if (!$invoice || $invoice->is_deleted || ! $invoice->is_public) {
return false; return false;
} }

View File

@ -103,6 +103,7 @@ class PaymentRepository extends BaseRepository
->where('payments.is_deleted', '=', false) ->where('payments.is_deleted', '=', false)
->where('invitations.deleted_at', '=', null) ->where('invitations.deleted_at', '=', null)
->where('invoices.is_deleted', '=', false) ->where('invoices.is_deleted', '=', false)
->where('invoices.is_public', '=', true)
->where('invitations.contact_id', '=', $contactId) ->where('invitations.contact_id', '=', $contactId)
->select( ->select(
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'), DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),

View File

@ -79,6 +79,7 @@ class InvoiceService extends BaseService
} }
} }
$wasPublic = $invoice ? $invoice->is_public : false;
$invoice = $this->invoiceRepo->save($data, $invoice); $invoice = $this->invoiceRepo->save($data, $invoice);
$client = $invoice->client; $client = $invoice->client;
@ -110,6 +111,10 @@ class InvoiceService extends BaseService
} }
} }
if ($invoice->is_public && ! $wasPublic) {
$invoice->markInvitationsSent();
}
return $invoice; return $invoice;
} }

View File

@ -1011,9 +1011,9 @@ $LANG = array(
'pro_plan_remove_logo' => ':link to remove the Invoice Ninja logo by joining the Pro Plan', 'pro_plan_remove_logo' => ':link to remove the Invoice Ninja logo by joining the Pro Plan',
'pro_plan_remove_logo_link' => 'Click here', 'pro_plan_remove_logo_link' => 'Click here',
'invitation_status_sent' => 'Email Sent', 'invitation_status_sent' => 'Sent',
'invitation_status_opened' => 'Email Openend', 'invitation_status_opened' => 'Openend',
'invitation_status_viewed' => 'Invoice Viewed', 'invitation_status_viewed' => 'Viewed',
'email_error_inactive_client' => 'Emails can not be sent to inactive clients', 'email_error_inactive_client' => 'Emails can not be sent to inactive clients',
'email_error_inactive_contact' => 'Emails can not be sent to inactive contacts', 'email_error_inactive_contact' => 'Emails can not be sent to inactive contacts',
'email_error_inactive_invoice' => 'Emails can not be sent to inactive invoices', 'email_error_inactive_invoice' => 'Emails can not be sent to inactive invoices',
@ -2257,6 +2257,7 @@ $LANG = array(
'force_pdfjs' => 'PDF Viewer', 'force_pdfjs' => 'PDF Viewer',
'redirect_url' => 'Redirect URL', 'redirect_url' => 'Redirect URL',
'redirect_url_help' => 'Optionally specify a URL to redirect to after a payment is made entered.', 'redirect_url_help' => 'Optionally specify a URL to redirect to after a payment is made entered.',
'save_draft' => 'Save Draft',
); );

View File

@ -527,7 +527,8 @@
{!! Former::text('entityType') !!} {!! Former::text('entityType') !!}
{!! Former::text('action') !!} {!! Former::text('action') !!}
{!! Former::text('public_id')->data_bind('value: public_id') !!} {!! Former::text('public_id')->data_bind('value: public_id') !!}
{!! Former::text('is_public')->data_bind('value: is_public') !!}
{!! Former::text('is_recurring')->data_bind('value: is_recurring') !!} {!! Former::text('is_recurring')->data_bind('value: is_recurring') !!}
{!! Former::text('is_quote')->data_bind('value: is_quote') !!} {!! Former::text('is_quote')->data_bind('value: is_quote') !!}
{!! Former::text('has_tasks')->data_bind('value: has_tasks') !!} {!! Former::text('has_tasks')->data_bind('value: has_tasks') !!}
@ -553,7 +554,12 @@
<!-- do nothing --> <!-- do nothing -->
@else @else
@if (!$invoice->is_deleted) @if (!$invoice->is_deleted)
{!! Button::success(trans("texts.save_{$entityType}"))->withAttributes(array('id' => 'saveButton', 'onclick' => 'onSaveClick()'))->appendIcon(Icon::create('floppy-disk')) !!} @if ($invoice->is_public)
{!! Button::success(trans("texts.save_{$entityType}"))->withAttributes(array('id' => 'saveButton', 'onclick' => 'onSaveClick()'))->appendIcon(Icon::create('floppy-disk')) !!}
@else
{!! Button::normal(trans("texts.save_draft"))->withAttributes(array('id' => 'saveButton', 'onclick' => 'onSaveClick()'))->appendIcon(Icon::create('floppy-disk')) !!}
{!! Button::success(trans("texts.mark_sent"))->withAttributes(array('id' => 'saveButton', 'onclick' => 'onMarkSentClick()'))->appendIcon(Icon::create('globe')) !!}
@endif
{!! Button::info(trans("texts.email_{$entityType}"))->withAttributes(array('id' => 'emailButton', 'onclick' => 'onEmailClick()'))->appendIcon(Icon::create('send')) !!} {!! Button::info(trans("texts.email_{$entityType}"))->withAttributes(array('id' => 'emailButton', 'onclick' => 'onEmailClick()'))->appendIcon(Icon::create('send')) !!}
@if (!$invoice->trashed()) @if (!$invoice->trashed())
@if ($invoice->id) @if ($invoice->id)
@ -1284,6 +1290,11 @@
}, getSendToEmails()); }, getSendToEmails());
} }
function onMarkSentClick() {
model.invoice().is_public(true);
onSaveClick();
}
function onSaveClick() { function onSaveClick() {
if (model.invoice().is_recurring()) { if (model.invoice().is_recurring()) {
// warn invoice will be emailed when saving new recurring invoice // warn invoice will be emailed when saving new recurring invoice
@ -1449,10 +1460,6 @@
return isValid; return isValid;
} }
function onMarkClick() {
submitBulkAction('markSent');
}
function onCloneClick() { function onCloneClick() {
submitAction('clone'); submitAction('clone');
} }

View File

@ -160,6 +160,7 @@ function ViewModel(data) {
function InvoiceModel(data) { function InvoiceModel(data) {
var self = this; var self = this;
this.client = ko.observable(data ? false : new ClientModel()); this.client = ko.observable(data ? false : new ClientModel());
this.is_public = ko.observable(0);
self.account = {!! $account !!}; self.account = {!! $account !!};
self.id = ko.observable(''); self.id = ko.observable('');
self.discount = ko.observable(''); self.discount = ko.observable('');