1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-15 15:42:51 +01:00
invoiceninja/resources/views/invoices/edit.blade.php

1735 lines
71 KiB
PHP
Raw Normal View History

2013-11-26 13:45:07 +01:00
@extends('header')
2017-06-13 14:55:34 +02:00
@section('head_css')
2013-12-08 14:32:49 +01:00
@parent
2017-06-13 14:55:34 +02:00
<link href="{{ asset('css/lightbox.css') }}" rel="stylesheet" type="text/css"/>
2017-02-05 22:29:11 +01:00
<link href="{{ asset('css/quill.snow.css') }}" rel="stylesheet" type="text/css"/>
2015-10-25 08:13:06 +01:00
2017-06-13 14:55:34 +02:00
<style type="text/css">
2016-03-31 11:29:01 +02:00
select.tax-select {
width: 50%;
float: left;
}
2016-04-11 12:30:23 +02:00
#scrollable-dropdown-menu .tt-menu {
max-height: 150px;
overflow-y: auto;
overflow-x: hidden;
}
2016-11-06 12:44:58 +01:00
.signature-wrapper .tooltip-inner {
width: 600px;
max-width: 600px;
padding: 20px;
}
2017-12-21 15:30:18 +01:00
.subtotals-table {
min-width: 340px;
}
.subtotals-table tr {
border-bottom: solid #CCCCCC 1px;
}
.subtotals-table td {
padding-top: 20px;
padding-bottom: 12px;
}
.subtotals-table input {
float: right;
text-align: right;
max-width: 150px;
}
2015-10-25 08:13:06 +01:00
</style>
2013-12-08 14:32:49 +01:00
@stop
2017-06-13 14:55:34 +02:00
@section('head')
@parent
@include('money_script')
@foreach ($account->getFontFolders() as $font)
<script src="{{ asset('js/vfs_fonts/'.$font.'.js') }}" type="text/javascript"></script>
@endforeach
<script src="{{ asset('pdf.built.js') }}?no_cache={{ NINJA_VERSION }}" type="text/javascript"></script>
<script src="{{ asset('js/lightbox.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/quill.min.js') }}" type="text/javascript"></script>
@stop
2013-11-26 13:45:07 +01:00
@section('content')
2015-11-04 08:48:47 +01:00
@if ($errors->first('invoice_items'))
<div class="alert alert-danger">{{ trans($errors->first('invoice_items')) }}</div>
@endif
2016-10-18 16:55:07 +02:00
@if ($invoice->id)
2014-02-17 00:09:34 +01:00
<ol class="breadcrumb">
2016-10-18 16:55:07 +02:00
@if ($invoice->is_recurring)
2017-10-22 16:40:34 +02:00
<li>{!! link_to('recurring_invoices', trans('texts.recurring_invoices')) !!}</li>
2016-10-18 16:55:07 +02:00
@else
<li>{!! link_to(($entityType == ENTITY_QUOTE ? 'quotes' : 'invoices'), trans('texts.' . ($entityType == ENTITY_QUOTE ? 'quotes' : 'invoices'))) !!}</li>
<li class="active">{{ $invoice->invoice_number }}</li>
@endif
@if ($invoice->is_recurring && $invoice->isSent())
@if (! $invoice->last_sent_date || $invoice->last_sent_date == '0000-00-00')
{!! $invoice->present()->statusLabel(trans('texts.pending')) !!}
@else
{!! $invoice->present()->statusLabel(trans('texts.active')) !!}
@endif
@else
{!! $invoice->present()->statusLabel !!}
@endif
2016-01-10 11:25:05 +01:00
</ol>
2014-02-17 00:09:34 +01:00
@endif
2014-01-01 16:23:32 +01:00
2015-11-09 15:53:18 +01:00
{!! Former::open($url)
->method($method)
2017-09-03 13:03:23 +02:00
->addClass('warn-on-exit main-form search')
2015-11-09 15:53:18 +01:00
->autocomplete('off')
2017-09-03 13:03:23 +02:00
->name('lastpass-disable-search') // 'search' prevents LastPass auto-fill http://stackoverflow.com/a/30921628/497368
->onsubmit('return onFormSubmit(event)')
2015-11-09 15:53:18 +01:00
->rules(array(
'client' => 'required',
'invoice_number' => 'required',
2016-09-21 16:07:01 +02:00
'invoice_date' => 'required',
2015-11-09 15:53:18 +01:00
'product_key' => 'max:255'
2016-01-10 11:25:05 +01:00
)) !!}
2015-11-09 15:53:18 +01:00
@include('partials.autocomplete_fix')
2015-04-20 16:34:23 +02:00
2014-03-17 19:05:01 +01:00
<input type="submit" style="display:none" name="submitButton" id="submitButton">
2014-01-01 16:23:32 +01:00
<div data-bind="with: invoice">
2015-04-20 16:34:23 +02:00
<div class="panel panel-default">
2016-03-27 17:06:02 +02:00
<div class="panel-body">
2015-04-20 16:34:23 +02:00
<div class="row" style="min-height:195px" onkeypress="formEnterClick(event)">
2014-02-16 23:03:19 +01:00
<div class="col-md-4" id="col_1">
2013-12-31 00:19:17 +01:00
2015-10-25 08:13:06 +01:00
@if ($invoice->id || $data)
2013-12-31 00:19:17 +01:00
<div class="form-group">
2016-09-21 16:07:01 +02:00
<label for="client" class="control-label col-lg-4 col-sm-4"><b>{{ trans('texts.client') }}</b></label>
2015-05-08 10:21:29 +02:00
<div class="col-lg-8 col-sm-8">
<h4>
<span data-bind="text: getClientDisplayName(ko.toJS(client()))"></span>
@if ($invoice->client->is_deleted)
&nbsp;&nbsp;<div class="label label-danger">{{ trans('texts.deleted') }}</div>
@endif
</h4>
2016-05-15 22:16:08 +02:00
2016-04-26 03:53:39 +02:00
@can('view', $invoice->client)
@can('edit', $invoice->client)
<a id="editClientLink" class="pointer" data-bind="click: $root.showClientForm">{{ trans('texts.edit_client') }}</a> |
2016-04-26 03:53:39 +02:00
@endcan
{!! link_to('/clients/'.$invoice->client->public_id, trans('texts.view_client'), ['target' => '_blank']) !!}
2016-04-26 03:53:39 +02:00
@endcan
2013-12-31 00:19:17 +01:00
</div>
2016-01-10 11:25:05 +01:00
</div>
2013-12-31 00:19:17 +01:00
<div style="display:none">
@endif
2016-05-15 22:16:08 +02:00
2017-04-09 22:25:02 +02:00
{!! Former::select('client')
->addOption('', '')
->data_bind("dropdown: client, dropdownOptions: {highlighter: comboboxHighlighter}")
2017-04-09 22:25:02 +02:00
->addClass('client-input')
->addGroupClass('client_select closer-row') !!}
<div class="form-group" style="margin-bottom: 8px">
2013-12-15 13:55:50 +01:00
<div class="col-lg-8 col-sm-8 col-lg-offset-4 col-sm-offset-4">
2015-08-11 16:38:36 +02:00
<a id="createClientLink" class="pointer" data-bind="click: $root.showClientForm, html: $root.clientLinkText"></a>
2016-01-10 11:25:05 +01:00
<span data-bind="visible: $root.invoice().client().public_id() > 0" style="display:none">|
2015-05-08 10:21:29 +02:00
<a data-bind="attr: {href: '{{ url('/clients') }}/' + $root.invoice().client().public_id()}" target="_blank">{{ trans('texts.view_client') }}</a>
</span>
</div>
</div>
2015-10-25 08:13:06 +01:00
@if ($invoice->id || $data)
2013-12-31 00:19:17 +01:00
</div>
@endif
2015-10-15 16:14:13 +02:00
<div data-bind="with: client" class="invoice-contact">
2017-02-21 14:27:04 +01:00
<div style="display:none" class="form-group" data-bind="visible: contacts().length > 0, foreach: contacts">
<div class="col-lg-8 col-lg-offset-4 col-sm-offset-4">
2017-03-31 11:26:50 +02:00
<label class="checkbox" data-bind="attr: {for: $index() + '_check'}, visible: email.display" onclick="refreshPDF(true)">
2015-11-06 08:54:29 +01:00
<input type="hidden" value="0" data-bind="attr: {name: 'client[contacts][' + $index() + '][send_invoice]'}">
2017-03-31 11:26:50 +02:00
<input type="checkbox" value="1" data-bind="visible: email() || first_name() || last_name(), checked: send_invoice, attr: {id: $index() + '_check', name: 'client[contacts][' + $index() + '][send_invoice]'}">
2017-08-04 15:39:11 +02:00
<span data-bind="visible: first_name || last_name">
2017-12-31 16:01:16 +01:00
<span data-bind="text: (first_name() || '') + ' ' + (last_name() || '')"></span>
2017-08-04 15:39:11 +02:00
<br/>
</span>
<span data-bind="visible: email">
<span data-bind="text: email"></span>
<br/>
</span>
2015-10-11 16:41:09 +02:00
</label>
@if ( ! $invoice->is_deleted && ! $invoice->client->is_deleted)
<span data-bind="visible: !$root.invoice().is_recurring()">
<span data-bind="html: $data.view_as_recipient"></span>&nbsp;&nbsp;
@if (Utils::isConfirmed())
2016-11-04 14:34:15 +01:00
<span style="vertical-align:text-top;color:red" class="fa fa-exclamation-triangle"
data-bind="visible: $data.email_error, tooltip: {title: $data.email_error}"></span>
2017-01-08 08:09:38 +01:00
<span style="vertical-align:text-top;padding-top:2px" class="fa fa-info-circle"
2016-11-04 14:34:15 +01:00
data-bind="visible: $data.invitation_status, tooltip: {title: $data.invitation_status, html: true},
style: {color: $data.info_color}"></span>
2016-11-06 12:44:58 +01:00
<span class="signature-wrapper">&nbsp;
<span style="vertical-align:text-top;color:#888" class="fa fa-user"
data-bind="visible: $data.invitation_signature_svg, tooltip: {title: $data.invitation_signature_svg, html: true}"></span>
</span>
@endif
</span>
@endif
2015-10-11 16:41:09 +02:00
</div>
</div>
</div>
2016-01-10 11:25:05 +01:00
2013-11-26 22:45:10 +01:00
</div>
2013-12-11 21:33:44 +01:00
<div class="col-md-4" id="col_2">
<div data-bind="visible: !is_recurring()">
2018-02-20 10:02:20 +01:00
{!! Former::text('invoice_date')->data_bind("datePicker: invoice_date, valueUpdate: 'afterkeydown'")->label($account->getLabel("{$entityType}_date"))
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))->appendIcon('calendar')->addGroupClass('invoice_date') !!}
{!! Former::text('due_date')->data_bind("datePicker: due_date, valueUpdate: 'afterkeydown'")->label($account->getLabel($invoice->getDueDateLabel()))
->placeholder($invoice->id ? ' ' : $account->present()->dueDatePlaceholder())
2015-09-07 11:07:55 +02:00
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))->appendIcon('calendar')->addGroupClass('due_date') !!}
2017-10-25 23:35:38 +02:00
<div class="form-group partial">
<label for="partial" class="control-label col-lg-4 col-sm-4">{{ trans('texts.partial') }}</label>
<div class="col-lg-8 col-sm-8 no-gutter">
<div data-bind="css: {'col-md-4': showPartialDueDate(), 'col-md-12': ! showPartialDueDate()}" class="partial">
2017-10-25 23:35:38 +02:00
{!! Former::text('partial')->data_bind("value: partial, valueUpdate: 'afterkeydown'")
->onkeyup('onPartialChange()')
->raw() !!}
</div>
<div class="col-lg-8 no-gap">
{!! Former::text('partial_due_date')
->placeholder('due_date')
->style('display: none')
->data_bind("datePicker: partial_due_date, valueUpdate: 'afterkeydown', visible: showPartialDueDate")
2017-10-25 23:35:38 +02:00
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))
->raw() !!}
</div>
</div>
</div>
2013-12-10 23:10:43 +01:00
</div>
2015-10-11 16:41:09 +02:00
@if ($entityType == ENTITY_INVOICE)
<div data-bind="visible: is_recurring" style="display: none">
2017-03-23 10:39:44 +01:00
{!! Former::select('frequency_id')->label('frequency')->options($frequencies)->data_bind("value: frequency_id")
->appendIcon('question-sign')->addGroupClass('frequency_id')->onchange('onFrequencyChange()') !!}
2015-10-11 16:41:09 +02:00
{!! Former::text('start_date')->data_bind("datePicker: start_date, valueUpdate: 'afterkeydown'")
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))->appendIcon('calendar')->addGroupClass('start_date') !!}
{!! Former::text('end_date')->data_bind("datePicker: end_date, valueUpdate: 'afterkeydown'")
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))->appendIcon('calendar')->addGroupClass('end_date') !!}
{!! Former::select('recurring_due_date')->label(trans('texts.due_date'))->options($recurringDueDates)->data_bind("value: recurring_due_date")->appendIcon('question-sign')->addGroupClass('recurring_due_date') !!}
2015-10-11 16:41:09 +02:00
</div>
@endif
2015-10-13 09:11:44 +02:00
@if ($account->showCustomField('custom_invoice_text_label1', $invoice))
@include('partials.custom_field', [
'field' => 'custom_text_value1',
'label' => $account->custom_invoice_text_label1,
'databind' => "value: custom_text_value1, valueUpdate: 'afterkeydown'",
])
2015-10-18 12:37:04 +02:00
@endif
2013-11-26 22:45:10 +01:00
</div>
2013-12-24 07:22:16 +01:00
2014-02-16 23:03:19 +01:00
<div class="col-md-4" id="col_2">
2015-08-14 14:04:33 +02:00
<span data-bind="visible: !is_recurring()">
{!! Former::text('invoice_number')
->label(trans("texts.{$entityType}_number_short"))
->onchange('checkInvoiceNumber()')
->addGroupClass('invoice-number')
->data_bind("value: invoice_number, valueUpdate: 'afterkeydown'") !!}
2016-01-10 11:25:05 +01:00
</span>
<span data-bind="visible: is_recurring()" style="display: none">
<div data-bind="visible: !(auto_bill() == {{AUTO_BILL_OPT_IN}} &amp;&amp; client_enable_auto_bill()) &amp;&amp; !(auto_bill() == {{AUTO_BILL_OPT_OUT}} &amp;&amp; !client_enable_auto_bill())" style="display: none">
2016-05-09 22:29:02 +02:00
{!! Former::select('auto_bill')
->data_bind("value: auto_bill, valueUpdate: 'afterkeydown', event:{change:function(){if(auto_bill()==".AUTO_BILL_OPT_IN.")client_enable_auto_bill(0);if(auto_bill()==".AUTO_BILL_OPT_OUT.")client_enable_auto_bill(1)}}")
2016-05-09 22:29:02 +02:00
->options([
AUTO_BILL_OFF => trans('texts.off'),
AUTO_BILL_OPT_IN => trans('texts.opt_in'),
AUTO_BILL_OPT_OUT => trans('texts.opt_out'),
AUTO_BILL_ALWAYS => trans('texts.always'),
2016-05-09 22:29:02 +02:00
]) !!}
</div>
<input type="hidden" name="client_enable_auto_bill" data-bind="attr: { value: client_enable_auto_bill() }" />
<div class="form-group" data-bind="visible: auto_bill() == {{AUTO_BILL_OPT_IN}} &amp;&amp; client_enable_auto_bill()">
2016-05-09 22:29:02 +02:00
<div class="col-sm-4 control-label">{{trans('texts.auto_bill')}}</div>
<div class="col-sm-8" style="padding-top:10px;padding-bottom:9px">
{{trans('texts.opted_in')}} - <a href="#" data-bind="click:function(){client_enable_auto_bill(false)}">({{trans('texts.disable')}})</a>
</div>
</div>
<div class="form-group" data-bind="visible: auto_bill() == {{AUTO_BILL_OPT_OUT}} &amp;&amp; !client_enable_auto_bill()">
2016-05-09 22:29:02 +02:00
<div class="col-sm-4 control-label">{{trans('texts.auto_bill')}}</div>
<div class="col-sm-8" style="padding-top:10px;padding-bottom:9px">
{{trans('texts.opted_out')}} - <a href="#" data-bind="click:function(){client_enable_auto_bill(true)}">({{trans('texts.enable')}})</a>
</div>
</div>
2015-08-14 14:04:33 +02:00
</span>
{!! Former::text('po_number')->label($account->getLabel('po_number', 'po_number_short'))->data_bind("value: po_number, valueUpdate: 'afterkeydown'") !!}
2015-03-27 06:02:19 +01:00
{!! Former::text('discount')->data_bind("value: discount, valueUpdate: 'afterkeydown'")
2017-10-25 23:35:38 +02:00
->addGroupClass('no-padding-or-border')->type('number')->min('0')->step('any')->append(
2017-08-15 17:36:17 +02:00
Former::select('is_amount_discount')
->addOption(trans('texts.discount_percent'), '0')
->addOption(trans('texts.discount_amount'), '1')
->data_bind("value: is_amount_discount, event:{ change: isAmountDiscountChanged}")
->raw()
2016-01-10 11:25:05 +01:00
) !!}
2015-10-11 16:41:09 +02:00
2015-10-13 09:11:44 +02:00
@if ($account->showCustomField('custom_invoice_text_label2', $invoice))
@include('partials.custom_field', [
'field' => 'custom_text_value2',
'label' => $account->custom_invoice_text_label2,
'databind' => "value: custom_text_value2, valueUpdate: 'afterkeydown'",
])
2015-10-11 16:41:09 +02:00
@endif
2016-01-11 20:41:02 +01:00
@if ($entityType == ENTITY_INVOICE)
<div class="form-group" style="margin-bottom: 8px">
2017-10-24 21:19:17 +02:00
<div class="col-lg-8 col-sm-8 col-sm-offset-4 smaller" style="padding-top: 10px;">
@if ($invoice->recurring_invoice)
2017-10-24 21:19:17 +02:00
{!! trans('texts.created_by_invoice', ['invoice' => link_to('/invoices/'.$invoice->recurring_invoice->public_id, trans('texts.recurring_invoice'))]) !!} <p/>
@elseif ($invoice->id)
@if (isset($lastSent) && $lastSent)
2017-10-24 21:19:17 +02:00
{!! trans('texts.last_sent_on', ['date' => link_to('/invoices/'.$lastSent->public_id, $invoice->last_sent_date, ['id' => 'lastSent'])]) !!} <p/>
@endif
@if ($invoice->is_recurring && $invoice->getNextSendDate())
{!! trans('texts.next_send_on', ['date' => '<span data-bind="tooltip: {title: \''.$invoice->getPrettySchedule().'\', html: true}">'.$account->formatDate($invoice->getNextSendDate()).
'<span class="glyphicon glyphicon-info-sign" style="padding-left:10px;color:#B1B5BA"></span></span>']) !!}
@if ($invoice->getDueDate())
<br>
{!! trans('texts.next_due_on', ['date' => '<span>'.$account->formatDate($invoice->getDueDate($invoice->getNextSendDate())).'</span>']) !!}
@endif
2017-10-24 21:19:17 +02:00
<p/>
@endif
@endif
</div>
</div>
@endif
2013-12-24 07:22:16 +01:00
</div>
2013-11-26 22:45:10 +01:00
</div>
2013-11-26 13:45:07 +01:00
2017-06-20 11:37:15 +02:00
<div class="table-responsive" style="padding-top:4px;">
2014-07-20 12:38:42 +02:00
2017-12-21 15:30:18 +01:00
@include('invoices.edit_table', ['isTasks' => false])
@if ($account->isModuleEnabled(ENTITY_TASK) && ($invoice->has_tasks || ! empty($tasks)))
@include('invoices.edit_table', ['isTasks' => true])
@endif
2014-07-20 12:38:42 +02:00
2017-12-21 15:30:18 +01:00
<table class="pull-right subtotals-table" style="margin-right:40px; margin-top:0px;">
<tr>
2017-10-29 11:39:15 +01:00
<td colspan="2">{{ trans('texts.subtotal') }}</td>
2014-01-01 16:23:32 +01:00
<td style="text-align: right"><span data-bind="text: totals.subtotal"/></td>
2014-05-22 20:29:29 +02:00
</tr>
2014-07-20 12:38:42 +02:00
2014-12-03 23:05:38 +01:00
<tr style="display:none" data-bind="visible: discount() != 0">
2017-10-29 11:39:15 +01:00
<td colspan="2">{{ trans('texts.discount') }}</td>
2014-01-01 16:23:32 +01:00
<td style="text-align: right"><span data-bind="text: totals.discounted"/></td>
2014-05-22 20:29:29 +02:00
</tr>
2014-07-20 12:38:42 +02:00
2017-03-16 19:20:08 +01:00
@if ($account->showCustomField('custom_invoice_label1', $invoice) && $invoice->custom_taxes1)
2014-07-20 12:38:42 +02:00
<tr>
2017-10-29 11:39:15 +01:00
<td colspan="2">{{ $account->custom_invoice_label1 ?: trans('texts.surcharge') }}</td>
2017-12-21 15:30:18 +01:00
<td><input name="custom_value1" class="form-control" data-bind="value: custom_value1, valueUpdate: 'afterkeydown'"/></td>
2014-07-20 12:38:42 +02:00
</tr>
@endif
2017-03-16 19:20:08 +01:00
@if ($account->showCustomField('custom_invoice_label2', $invoice) && $invoice->custom_taxes2)
2014-07-20 12:38:42 +02:00
<tr>
2017-10-29 11:39:15 +01:00
<td colspan="2">{{ $account->custom_invoice_label2 ?: trans('texts.surcharge') }}</td>
2017-12-21 15:30:18 +01:00
<td><input name="custom_value2" class="form-control" data-bind="value: custom_value2, valueUpdate: 'afterkeydown'"/></td>
2014-07-20 12:38:42 +02:00
</tr>
@endif
<tr style="display:none" data-bind="visible: $root.invoice_item_taxes.show &amp;&amp; totals.hasItemTaxes">
2017-12-21 15:30:18 +01:00
<td>{{ trans('texts.tax') }}&nbsp;&nbsp;</td>
<td style="min-width:120px"><span data-bind="html: totals.itemTaxRates"/></td>
<td style="text-align: right"><span data-bind="html: totals.itemTaxAmounts"/></td>
</tr>
2014-05-22 20:29:29 +02:00
<tr style="display:none" data-bind="visible: $root.invoice_taxes.show">
2017-12-21 15:30:18 +01:00
<td>{{ trans('texts.tax') }}&nbsp;&nbsp;</td>
2015-10-28 20:22:07 +01:00
<td style="min-width:120px">
2016-03-27 17:06:02 +02:00
{!! Former::select('')
2016-04-11 10:48:46 +02:00
->id('taxRateSelect1')
2016-03-29 16:30:28 +02:00
->addOption('', '')
->options($taxRateOptions)
2016-05-29 11:26:02 +02:00
->addClass($account->enable_second_tax_rate ? 'tax-select' : '')
2017-01-02 12:38:58 +01:00
->data_bind('value: tax1, event:{change:onTax1Change}')
2016-05-15 22:16:08 +02:00
->raw() !!}
2016-03-31 11:29:01 +02:00
<input type="text" name="tax_name1" data-bind="value: tax_name1" style="display:none">
<input type="text" name="tax_rate1" data-bind="value: tax_rate1" style="display:none">
2016-05-29 11:26:02 +02:00
<div data-bind="visible: $root.invoice().account.enable_second_tax_rate == '1'">
2016-03-31 11:29:01 +02:00
{!! Former::select('')
->addOption('', '')
->options($taxRateOptions)
->addClass('tax-select')
2017-01-02 12:38:58 +01:00
->data_bind('value: tax2, event:{change:onTax2Change}')
2016-05-15 22:16:08 +02:00
->raw() !!}
2016-05-29 11:26:02 +02:00
</div>
2016-03-31 11:29:01 +02:00
<input type="text" name="tax_name2" data-bind="value: tax_name2" style="display:none">
<input type="text" name="tax_rate2" data-bind="value: tax_rate2" style="display:none">
2015-10-28 20:22:07 +01:00
</td>
2014-03-10 12:04:15 +01:00
<td style="text-align: right"><span data-bind="text: totals.taxAmount"/></td>
2014-05-22 20:29:29 +02:00
</tr>
2014-07-20 12:38:42 +02:00
2017-03-16 19:20:08 +01:00
@if ($account->showCustomField('custom_invoice_label1', $invoice) && !$invoice->custom_taxes1)
2014-07-20 12:38:42 +02:00
<tr>
2017-10-29 11:39:15 +01:00
<td colspan="2">{{ $account->custom_invoice_label1 ?: trans('texts.surcharge') }}</td>
2017-12-21 15:30:18 +01:00
<td><input name="custom_value1" class="form-control" data-bind="value: custom_value1, valueUpdate: 'afterkeydown'"/></td>
2014-07-20 12:38:42 +02:00
</tr>
@endif
2017-03-16 19:20:08 +01:00
@if ($account->showCustomField('custom_invoice_label2', $invoice) && !$invoice->custom_taxes2)
2014-07-20 12:38:42 +02:00
<tr>
2017-10-29 11:39:15 +01:00
<td colspan="2">{{ $account->custom_invoice_label2 ?: trans('texts.surcharge') }}</td>
2017-12-21 15:30:18 +01:00
<td><input name="custom_value2" class="form-control" data-bind="value: custom_value2, valueUpdate: 'afterkeydown'"/></td>
2014-07-20 12:38:42 +02:00
</tr>
@endif
@if (!$account->hide_paid_to_date)
<tr>
2017-10-29 11:39:15 +01:00
<td colspan="2">{{ trans('texts.paid_to_date') }}</td>
2014-07-20 12:38:42 +02:00
<td style="text-align: right" data-bind="text: totals.paidToDate"></td>
2015-10-28 20:22:07 +01:00
</tr>
2014-07-20 12:38:42 +02:00
@endif
2017-12-31 10:13:16 +01:00
<tr data-bind="style: { 'font-weight': partial() ? 'normal' : 'bold', 'font-size': partial() ? '1em' : '1.05em' }" style="font-size:1.05em;font-weight:bold;">
2017-10-29 11:39:15 +01:00
<td class="hide-border" data-bind="css: {'hide-border': !partial()}" colspan="2">{{ $entityType == ENTITY_INVOICE ? $invoiceLabels['balance_due'] : trans('texts.total') }}</td>
2016-03-18 13:34:46 +01:00
<td class="hide-border" data-bind="css: {'hide-border': !partial()}" style="text-align: right"><span data-bind="text: totals.total"></span></td>
</tr>
<tr style="font-size:1.05em; display:none; font-weight:bold" data-bind="visible: partial">
2017-10-29 11:39:15 +01:00
<td class="hide-border" colspan="2">{{ $invoiceLabels['partial_due'] }}</td>
2016-03-18 13:34:46 +01:00
<td class="hide-border" style="text-align: right"><span data-bind="text: totals.partial"></span></td>
2014-05-22 20:29:29 +02:00
</tr>
2017-12-21 15:30:18 +01:00
</table>
<div role="tabpanel" class="pull-left" style="margin-left:40px; margin-top:30px;">
<ul class="nav nav-tabs" role="tablist" style="border: none">
<li role="presentation" class="active"><a href="#public_notes" aria-controls="notes" role="tab" data-toggle="tab">{{ trans('texts.public_notes') }}</a></li>
<li role="presentation"><a href="#private_notes" aria-controls="terms" role="tab" data-toggle="tab">{{ trans("texts.private_notes") }}</a></li>
<li role="presentation"><a href="#terms" aria-controls="terms" role="tab" data-toggle="tab">{{ trans("texts.terms") }}</a></li>
<li role="presentation"><a href="#footer" aria-controls="footer" role="tab" data-toggle="tab">{{ trans("texts.footer") }}</a></li>
@if ($account->hasFeature(FEATURE_DOCUMENTS))
<li role="presentation"><a href="#attached-documents" aria-controls="attached-documents" role="tab" data-toggle="tab">
{{ trans("texts.documents") }}
@if ($count = ($invoice->countDocuments($expenses)))
({{ $count }})
@endif
</a></li>
@endif
</ul>
{{ Former::setOption('TwitterBootstrap3.labelWidths.large', 0) }}
{{ Former::setOption('TwitterBootstrap3.labelWidths.small', 0) }}
<div class="tab-content" style="padding-right:12px;max-width:600px;">
<div role="tabpanel" class="tab-pane active" id="public_notes" style="padding-bottom:44px;">
{!! Former::textarea('public_notes')
->data_bind("value: public_notes, valueUpdate: 'afterkeydown'")
->label(null)->style('width: 100%')->rows(4)->label(null) !!}
</div>
<div role="tabpanel" class="tab-pane" id="private_notes" style="padding-bottom:44px">
{!! Former::textarea('private_notes')
->data_bind("value: private_notes, valueUpdate: 'afterkeydown'")
->label(null)->style('width: 100%')->rows(4) !!}
</div>
<div role="tabpanel" class="tab-pane" id="terms">
{!! Former::textarea('terms')
->data_bind("value:terms, placeholder: terms_placeholder, valueUpdate: 'afterkeydown'")
->label(false)->style('width: 100%')->rows(4)
->help('<div class="checkbox">
<label>
<input name="set_default_terms" type="checkbox" style="width: 16px" data-bind="checked: set_default_terms"/>'.trans('texts.save_as_default_terms').'
</label>
<div class="pull-right" data-bind="visible: showResetTerms()">
<a href="#" onclick="return resetTerms()" title="'. trans('texts.reset_terms_help') .'">' . trans("texts.reset_terms") . '</a>
</div>
</div>') !!}
</div>
<div role="tabpanel" class="tab-pane" id="footer">
{!! Former::textarea('invoice_footer')
->data_bind("value:invoice_footer, placeholder: footer_placeholder, valueUpdate: 'afterkeydown'")
->label(false)->style('width: 100%')->rows(4)
->help('<div class="checkbox">
<label>
<input name="set_default_footer" type="checkbox" style="width: 16px" data-bind="checked: set_default_footer"/>'.trans('texts.save_as_default_footer').'
</label>
<div class="pull-right" data-bind="visible: showResetFooter()">
<a href="#" onclick="return resetFooter()" title="'. trans('texts.reset_footer_help') .'">' . trans("texts.reset_footer") . '</a>
</div>
</div>') !!}
</div>
@if ($account->hasFeature(FEATURE_DOCUMENTS))
<div role="tabpanel" class="tab-pane" id="attached-documents" style="position:relative;z-index:9">
<div id="document-upload">
<div class="dropzone">
<div data-bind="foreach: documents">
<input type="hidden" name="document_ids[]" data-bind="value: public_id"/>
</div>
</div>
2018-03-05 15:40:10 +01:00
@if ($invoice->hasExpenseDocuments() || $expenses->count())
2017-12-21 15:30:18 +01:00
<h4>{{trans('texts.documents_from_expenses')}}</h4>
@foreach($invoice->expenses as $expense)
@if ($expense->invoice_documents)
@foreach($expense->documents as $document)
<div>{{$document->name}}</div>
@endforeach
@endif
@endforeach
@foreach($expenses as $expense)
@if ($expense->invoice_documents)
@foreach($expense->documents as $document)
<div>{{$document->name}}</div>
@endforeach
@endif
@endforeach
@endif
</div>
</div>
@endif
</div>
2017-12-23 20:37:36 +01:00
{{ Former::setOption('TwitterBootstrap3.labelWidths.large', 4) }}
{{ Former::setOption('TwitterBootstrap3.labelWidths.small', 4) }}
2017-12-21 15:30:18 +01:00
</div>
2014-07-20 12:38:42 +02:00
2015-04-20 16:34:23 +02:00
</div>
2017-12-21 15:30:18 +01:00
</div>
</div>
2016-01-10 11:25:05 +01:00
2017-11-03 09:19:03 +01:00
<center class="buttons">
2013-12-03 18:32:33 +01:00
2013-12-07 19:45:00 +01:00
<div style="display:none">
2015-03-27 06:02:19 +01:00
{!! Former::populateField('entityType', $entityType) !!}
2015-10-28 20:22:07 +01:00
2015-03-27 06:02:19 +01:00
{!! Former::text('entityType') !!}
{!! Former::text('action') !!}
{!! Former::text('public_id')->data_bind('value: public_id') !!}
{!! Former::text('is_public')->data_bind('value: is_public') !!}
2015-10-28 20:22:07 +01:00
{!! Former::text('is_recurring')->data_bind('value: is_recurring') !!}
{!! Former::text('is_quote')->data_bind('value: is_quote') !!}
{!! Former::text('has_tasks')->data_bind('value: has_tasks') !!}
{!! Former::text('data')->data_bind('value: ko.mapping.toJSON(model)') !!}
2016-01-10 11:25:05 +01:00
{!! Former::text('has_expenses')->data_bind('value: has_expenses') !!}
2015-10-28 20:22:07 +01:00
{!! Former::text('pdfupload') !!}
2013-12-07 19:45:00 +01:00
</div>
2017-06-01 18:13:13 +02:00
@if (!Utils::hasFeature(FEATURE_MORE_INVOICE_DESIGNS))
2015-07-21 20:51:56 +02:00
{!! Former::select('invoice_design_id')->style('display:inline;width:150px;background-color:white !important')->raw()->fromQuery($invoiceDesigns, 'name', 'id')->data_bind("value: invoice_design_id")->addOption(trans('texts.more_designs') . '...', '-1') !!}
2016-01-10 11:25:05 +01:00
@else
2015-07-21 20:51:56 +02:00
{!! Former::select('invoice_design_id')->style('display:inline;width:150px;background-color:white !important')->raw()->fromQuery($invoiceDesigns, 'name', 'id')->data_bind("value: invoice_design_id") !!}
@endif
2014-02-21 06:26:40 +01:00
@if ( $invoice->id && ! $invoice->is_recurring)
2018-02-11 19:03:48 +01:00
{!! Button::primary(trans('texts.download'))
->withAttributes(['onclick' => 'onDownloadClick()', 'id' => 'downloadPdfButton'])
->appendIcon(Icon::create('download-alt')) !!}
@endif
@if (Auth::user()->canCreateOrEdit(ENTITY_INVOICE, $invoice))
@if ($invoice->isClientTrashed())
<!-- do nothing -->
@elseif ($invoice->isLocked())
2017-11-05 11:39:35 +01:00
@if (! $invoice->trashed())
{!! Button::info(trans("texts.email_{$entityType}"))->withAttributes(array('id' => 'emailButton', 'onclick' => 'onEmailClick()'))->appendIcon(Icon::create('send')) !!}
{!! DropdownButton::normal(trans('texts.more_actions'))->withContents($invoice->present()->moreActions())->dropup() !!}
2017-11-05 11:39:35 +01:00
@endif
2016-10-10 10:40:04 +02:00
@else
2017-10-18 13:01:53 +02:00
@if (!$invoice->is_deleted)
@if ($invoice->isSent())
{!! 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' => 'draftButton', 'onclick' => 'onSaveDraftClick()'))->appendIcon(Icon::create('floppy-disk')) !!}
2017-02-20 12:47:25 +01:00
@if (! $invoice->trashed())
2017-03-09 14:08:18 +01:00
{!! Button::success(trans($invoice->is_recurring ? "texts.mark_ready" : "texts.mark_sent"))->withAttributes(array('id' => 'saveButton', 'onclick' => 'onMarkSentClick()'))->appendIcon(Icon::create('globe')) !!}
2017-02-20 12:47:25 +01:00
@endif
@endif
2017-02-20 12:47:25 +01:00
@if (! $invoice->trashed())
{!! Button::info(trans("texts.email_{$entityType}"))->withAttributes(array('id' => 'emailButton', 'onclick' => 'onEmailClick()'))->appendIcon(Icon::create('send')) !!}
@endif
@if ($invoice->id)
{!! DropdownButton::normal(trans('texts.more_actions'))->withContents($invoice->present()->moreActions())->dropup() !!}
@elseif (! $invoice->isQuote() && Request::is('*/clone'))
2017-02-20 12:47:25 +01:00
{!! Button::normal(trans($invoice->is_recurring ? 'texts.disable_recurring' : 'texts.enable_recurring'))->withAttributes(['id' => 'recurrButton', 'onclick' => 'onRecurrClick()'])->appendIcon(Icon::create('repeat')) !!}
@elseif (! empty($tasks))
2017-11-02 11:08:29 +01:00
{!! Button::normal(trans('texts.add_product'))->withAttributes(['id' => 'addItemButton', 'onclick' => 'onAddItemClick()'])->appendIcon(Icon::create('plus-sign')) !!}
2016-10-10 10:40:04 +02:00
@endif
@endif
@if ($invoice->trashed())
{!! Button::primary(trans('texts.restore'))->withAttributes(['onclick' => 'submitBulkAction("restore")'])->appendIcon(Icon::create('cloud-download')) !!}
@endif
2016-10-10 10:40:04 +02:00
@endif
@endif
2014-01-15 15:01:24 +01:00
2017-11-03 09:19:03 +01:00
</center>
2014-10-12 20:11:41 +02:00
@include('invoices.pdf', ['account' => Auth::user()->account, 'hide_pdf' => ! Auth::user()->account->live_preview])
2013-11-26 13:45:07 +01:00
2014-04-25 15:04:57 +02:00
@if (!Auth::user()->account->isPro())
2014-04-23 14:47:44 +02:00
<div style="font-size:larger">
2016-10-16 15:38:04 +02:00
{!! trans('texts.pro_plan_remove_logo', ['link'=>'<a href="javascript:showUpgradeModal()">' . trans('texts.pro_plan_remove_logo_link') . '</a>']) !!}
2014-04-23 14:47:44 +02:00
</div>
2014-04-03 22:01:03 +02:00
@endif
2013-11-26 13:45:07 +01:00
2013-12-27 10:10:32 +01:00
<div class="modal fade" id="clientModal" tabindex="-1" role="dialog" aria-labelledby="clientModalLabel" aria-hidden="true">
2015-04-20 16:34:23 +02:00
<div class="modal-dialog" data-bind="css: {'large-dialog': $root.showMore}">
<div class="modal-content" style="background-color: #f8f8f8">
2013-11-26 13:45:07 +01:00
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
2014-03-27 13:25:31 +01:00
<h4 class="modal-title" id="clientModalLabel">{{ trans('texts.client') }}</h4>
2013-11-26 13:45:07 +01:00
</div>
2013-12-05 21:25:20 +01:00
2015-04-20 16:34:23 +02:00
<div class="container" style="width: 100%; padding-bottom: 0px !important">
<div class="panel panel-default">
<div class="panel-body">
<div class="row" data-bind="with: client" onkeypress="clientModalEnterClick(event)">
<div style="margin-left:0px;margin-right:0px" data-bind="css: {'col-md-6': $root.showMore}">
2015-10-28 20:22:07 +01:00
{!! Former::hidden('client_public_id')->data_bind("value: public_id, valueUpdate: 'afterkeydown',
attr: {name: 'client[public_id]'}") !!}
{!! Former::text('client[name]')
->data_bind("value: name, valueUpdate: 'afterkeydown', attr { placeholder: name.placeholder }")
->label('client_name') !!}
2017-01-03 20:48:40 +01:00
@if ( ! $account->client_number_counter)
2015-04-20 16:34:23 +02:00
<span data-bind="visible: $root.showMore">
2017-01-03 20:48:40 +01:00
@endif
2016-01-19 14:01:19 +01:00
2017-01-03 20:48:40 +01:00
{!! Former::text('client[id_number]')
2015-10-28 20:22:07 +01:00
->label('id_number')
2017-01-04 09:11:32 +01:00
->placeholder($account->clientNumbersEnabled() ? $account->getNextNumber() : ' ')
2015-10-28 20:22:07 +01:00
->data_bind("value: id_number, valueUpdate: 'afterkeydown'") !!}
2017-01-03 20:48:40 +01:00
@if ( ! $account->client_number_counter)
</span>
@endif
<span data-bind="visible: $root.showMore">
2015-10-28 20:22:07 +01:00
{!! Former::text('client[vat_number]')
->label('vat_number')
->data_bind("value: vat_number, valueUpdate: 'afterkeydown'") !!}
2016-01-10 11:25:05 +01:00
2015-10-28 20:22:07 +01:00
{!! Former::text('client[website]')
->label('website')
->data_bind("value: website, valueUpdate: 'afterkeydown'") !!}
{!! Former::text('client[work_phone]')
->label('work_phone')
->data_bind("value: work_phone, valueUpdate: 'afterkeydown'") !!}
2016-05-15 22:16:08 +02:00
2015-10-25 08:49:10 +01:00
</span>
2015-04-20 16:34:23 +02:00
@if (Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS))
2015-10-25 08:49:10 +01:00
@if ($account->custom_client_label1)
@include('partials.custom_field', [
'field' => 'client[custom_value1]',
'label' => $account->custom_client_label1,
'databind' => "value: custom_value1, valueUpdate: 'afterkeydown'",
])
2015-10-25 08:49:10 +01:00
@endif
@if ($account->custom_client_label2)
@include('partials.custom_field', [
'field' => 'client[custom_value2]',
'label' => $account->custom_client_label2,
'databind' => "value: custom_value1, valueUpdate: 'afterkeydown'",
])
2015-10-25 08:49:10 +01:00
@endif
@endif
2015-04-20 16:34:23 +02:00
2015-10-25 08:49:10 +01:00
<span data-bind="visible: $root.showMore">
2015-04-20 16:34:23 +02:00
&nbsp;
2015-10-28 20:22:07 +01:00
{!! Former::text('client[address1]')
->label(trans('texts.address1'))
->data_bind("value: address1, valueUpdate: 'afterkeydown'") !!}
{!! Former::text('client[address2]')
->label(trans('texts.address2'))
->data_bind("value: address2, valueUpdate: 'afterkeydown'") !!}
{!! Former::text('client[city]')
->label(trans('texts.city'))
->data_bind("value: city, valueUpdate: 'afterkeydown'") !!}
{!! Former::text('client[state]')
->label(trans('texts.state'))
->data_bind("value: state, valueUpdate: 'afterkeydown'") !!}
{!! Former::text('client[postal_code]')
->label(trans('texts.postal_code'))
->data_bind("value: postal_code, valueUpdate: 'afterkeydown'") !!}
{!! Former::select('client[country_id]')
->label(trans('texts.country_id'))
->addOption('','')->addGroupClass('country_select')
2017-08-16 14:45:55 +02:00
->fromQuery($countries, 'name', 'id')
->data_bind("dropdown: country_id") !!}
2015-04-20 16:34:23 +02:00
</span>
</div>
<div style="margin-left:0px;margin-right:0px" data-bind="css: {'col-md-6': $root.showMore}">
<div data-bind='template: { foreach: contacts,
beforeRemove: hideContact,
afterAdd: showContact }'>
2015-10-28 20:22:07 +01:00
{!! Former::hidden('public_id')->data_bind("value: public_id, valueUpdate: 'afterkeydown',
attr: {name: 'client[contacts][' + \$index() + '][public_id]'}") !!}
2016-01-10 11:25:05 +01:00
{!! Former::text('first_name')->data_bind("value: first_name, valueUpdate: 'afterkeydown',
2015-10-28 20:22:07 +01:00
attr: {name: 'client[contacts][' + \$index() + '][first_name]'}") !!}
{!! Former::text('last_name')->data_bind("value: last_name, valueUpdate: 'afterkeydown',
attr: {name: 'client[contacts][' + \$index() + '][last_name]'}") !!}
2016-01-10 11:25:05 +01:00
{!! Former::text('email')->data_bind("value: email, valueUpdate: 'afterkeydown',
2015-11-09 12:46:53 +01:00
attr: {name: 'client[contacts][' + \$index() + '][email]', id:'email'+\$index()}")
->addClass('client-email') !!}
2015-10-28 20:22:07 +01:00
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown',
attr: {name: 'client[contacts][' + \$index() + '][phone]'}") !!}
@if ($account->hasFeature(FEATURE_CLIENT_PORTAL_PASSWORD) && $account->enable_portal_password)
{!! Former::password('password')->data_bind("value: (typeof password=='function'?password():null)?'-%unchanged%-':'', valueUpdate: 'afterkeydown',
2018-01-15 17:20:53 +01:00
attr: {name: 'client[contacts][' + \$index() + '][password]'}")->autocomplete('new-password')->data_lpignore('true') !!}
@endif
2017-04-16 13:31:14 +02:00
@if (Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS))
@if ($account->custom_contact_label1)
@include('partials.custom_field', [
'field' => 'custom_contact1',
'label' => $account->custom_contact_label1,
'databind' => "value: custom_value1, valueUpdate: 'afterkeydown',
attr: {name: 'client[contacts][' + \$index() + '][custom_value1]'}",
])
2017-04-16 13:31:14 +02:00
@endif
@if ($account->custom_contact_label2)
@include('partials.custom_field', [
'field' => 'custom_contact2',
'label' => $account->custom_contact_label2,
'databind' => "value: custom_value2, valueUpdate: 'afterkeydown',
attr: {name: 'client[contacts][' + \$index() + '][custom_value2]'}",
])
2017-04-16 13:31:14 +02:00
@endif
@endif
2015-04-20 16:34:23 +02:00
<div class="form-group">
<div class="col-lg-8 col-lg-offset-4">
<span class="redlink bold" data-bind="visible: $parent.contacts().length > 1">
{!! link_to('#', trans('texts.remove_contact').' -', array('data-bind'=>'click: $parent.removeContact')) !!}
2016-01-10 11:25:05 +01:00
</span>
2015-04-20 16:34:23 +02:00
<span data-bind="visible: $index() === ($parent.contacts().length - 1)" class="pull-right greenlink bold">
{!! link_to('#', trans('texts.add_contact').' +', array('data-bind'=>'click: $parent.addContact')) !!}
</span>
</div>
</div>
</div>
2013-12-05 21:25:20 +01:00
2015-10-25 08:49:10 +01:00
<span data-bind="visible: $root.showMore">
2015-04-20 16:34:23 +02:00
&nbsp;
</span>
2015-10-28 20:22:07 +01:00
{!! Former::select('client[currency_id]')->addOption('','')
2017-12-01 08:28:01 +01:00
->placeholder($account->currency ? trans('texts.currency_'.Str::slug($account->currency->name, '_')) : '')
2015-10-28 20:22:07 +01:00
->label(trans('texts.currency_id'))
->data_bind('value: currency_id')
->fromQuery($currencies, 'name', 'id') !!}
2015-04-20 16:34:23 +02:00
<span data-bind="visible: $root.showMore">
2015-10-28 20:22:07 +01:00
{!! Former::select('client[language_id]')->addOption('','')
2017-12-01 08:28:01 +01:00
->placeholder($account->language ? trans('texts.lang_'.$account->language->name) : '')
2015-10-28 20:22:07 +01:00
->label(trans('texts.language_id'))
->data_bind('value: language_id')
2016-01-10 11:25:05 +01:00
->fromQuery($languages, 'name', 'id') !!}
2015-10-28 20:22:07 +01:00
{!! Former::select('client[payment_terms]')->addOption('','')->data_bind('value: payment_terms')
->fromQuery(\App\Models\PaymentTerm::getSelectOptions(), 'name', 'num_days')
2015-10-28 20:22:07 +01:00
->label(trans('texts.payment_terms'))
->help(trans('texts.payment_terms_help')) !!}
{!! Former::select('client[size_id]')->addOption('','')->data_bind('value: size_id')
->label(trans('texts.size_id'))
->fromQuery($sizes, 'name', 'id') !!}
{!! Former::select('client[industry_id]')->addOption('','')->data_bind('value: industry_id')
->label(trans('texts.industry_id'))
->fromQuery($industries, 'name', 'id') !!}
{!! Former::textarea('client_private_notes')
->label(trans('texts.private_notes'))
->data_bind("value: private_notes, attr:{ name: 'client[private_notes]'}") !!}
2015-04-20 16:34:23 +02:00
</span>
</div>
</div>
</div>
</div>
</div>
2017-03-26 10:45:17 +02:00
<div class="modal-footer">
2015-04-30 19:54:19 +02:00
<span class="error-block" id="emailError" style="display:none;float:left;font-weight:bold">{{ trans('texts.provide_name_or_email') }}</span><span>&nbsp;</span>
2015-04-20 16:34:23 +02:00
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('texts.cancel') }}</button>
<button type="button" class="btn btn-default" data-bind="click: $root.showMoreFields, text: $root.showMore() ? '{{ trans('texts.less_fields') }}' : '{{ trans('texts.more_fields') }}'"></button>
2016-01-10 11:25:05 +01:00
<button id="clientDoneButton" type="button" class="btn btn-primary" data-bind="click: $root.clientFormComplete">{{ trans('texts.done') }}</button>
2015-04-20 16:34:23 +02:00
</div>
2016-01-10 11:25:05 +01:00
2015-04-20 16:34:23 +02:00
</div>
</div>
</div>
2013-12-27 10:10:32 +01:00
2014-01-15 15:01:24 +01:00
<div class="modal fade" id="recurringModal" tabindex="-1" role="dialog" aria-labelledby="recurringModalLabel" aria-hidden="true">
<div class="modal-dialog" style="min-width:150px">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
2014-03-27 13:25:31 +01:00
<h4 class="modal-title" id="recurringModalLabel">{{ trans('texts.recurring_invoices') }}</h4>
2014-01-15 15:01:24 +01:00
</div>
2017-02-19 12:55:46 +01:00
<div class="container" style="width: 100%; padding-bottom: 0px !important">
<div class="panel panel-default">
<div class="panel-body">
{!! isset($recurringHelp) ? $recurringHelp : '' !!}
</div>
</div>
</div>
2017-05-25 20:01:22 +02:00
<div class="modal-footer">
2014-04-10 21:29:01 +02:00
<button type="button" class="btn btn-primary" data-dismiss="modal">{{ trans('texts.close') }}</button>
2014-01-15 15:01:24 +01:00
</div>
2016-01-10 11:25:05 +01:00
2014-01-15 15:01:24 +01:00
</div>
</div>
</div>
2016-01-11 20:41:02 +01:00
<div class="modal fade" id="recurringDueDateModal" tabindex="-1" role="dialog" aria-labelledby="recurringDueDateModalLabel" aria-hidden="true">
<div class="modal-dialog" style="min-width:150px">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="recurringDueDateModalLabel">{{ trans('texts.recurring_due_dates') }}</h4>
</div>
2017-02-19 12:55:46 +01:00
<div class="container" style="width: 100%; padding-bottom: 0px !important">
<div class="panel panel-default">
<div class="panel-body">
{!! isset($recurringDueDateHelp) ? $recurringDueDateHelp : '' !!}
</div>
</div>
</div>
2017-05-25 20:01:22 +02:00
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">{{ trans('texts.close') }}</button>
</div>
2016-01-11 20:41:02 +01:00
</div>
</div>
</div>
2014-01-15 15:01:24 +01:00
2017-02-05 13:48:26 +01:00
@include('partials.email_templates')
2017-02-05 08:53:49 +01:00
@include('invoices.email')
{!! Former::close() !!}
</form>
2014-01-15 15:01:24 +01:00
2015-10-28 20:22:07 +01:00
{!! Former::open("{$entityType}s/bulk")->addClass('bulkForm') !!}
{!! Former::populateField('bulk_public_id', $invoice->public_id) !!}
<span style="display:none">
{!! Former::text('bulk_public_id') !!}
{!! Former::text('bulk_action') !!}
</span>
{!! Former::close() !!}
2015-04-20 16:34:23 +02:00
</div>
2013-11-26 13:45:07 +01:00
2015-10-22 20:48:12 +02:00
@include('invoices.knockout')
2013-11-26 13:45:07 +01:00
<script type="text/javascript">
2016-03-23 03:23:45 +01:00
Dropzone.autoDiscover = false;
2016-01-10 11:25:05 +01:00
2017-05-08 21:10:39 +02:00
var products = {!! $products !!};
var clients = {!! $clients !!};
2015-10-22 20:48:12 +02:00
var account = {!! Auth::user()->account !!};
2016-03-23 03:23:45 +01:00
var dropzone;
2015-10-22 20:48:12 +02:00
var clientMap = {};
var $clientSelect = $('select#client');
var invoiceDesigns = {!! $invoiceDesigns !!};
2016-01-07 08:08:30 +01:00
var invoiceFonts = {!! $invoiceFonts !!};
2016-05-15 22:16:08 +02:00
2013-11-26 13:45:07 +01:00
$(function() {
2015-10-22 20:48:12 +02:00
// create client dictionary
for (var i=0; i<clients.length; i++) {
var client = clients[i];
2017-02-21 14:15:55 +01:00
clientMap[client.public_id] = client;
2017-03-26 12:19:07 +02:00
@if (! $invoice->id)
2017-04-09 22:25:02 +02:00
if (!getClientDisplayName(client)) {
2017-03-26 12:19:07 +02:00
continue;
}
@endif
var clientName = client.name || '';
2017-04-09 22:25:02 +02:00
for (var j=0; j<client.contacts.length; j++) {
2015-10-22 20:48:12 +02:00
var contact = client.contacts[j];
2017-04-09 22:25:02 +02:00
var contactName = getContactDisplayNameWithEmail(contact);
if (clientName && contactName) {
clientName += '<br/> • ';
}
if (contactName) {
clientName += contactName;
}
2015-10-22 20:48:12 +02:00
}
2016-01-10 11:25:05 +01:00
$clientSelect.append(new Option(clientName, client.public_id));
2015-10-22 20:48:12 +02:00
}
@if ($data)
// this means we failed so we'll reload the previous state
window.model = new ViewModel({!! $data !!});
2016-01-10 11:25:05 +01:00
@else
2015-10-22 20:48:12 +02:00
// otherwise create blank model
window.model = new ViewModel();
2017-05-08 21:10:39 +02:00
var invoice = {!! $invoice !!};
2015-10-23 13:55:18 +02:00
ko.mapping.fromJS(invoice, model.invoice().mapping, model.invoice);
2015-10-28 20:22:07 +01:00
model.invoice().is_recurring({{ $invoice->is_recurring ? '1' : '0' }});
model.invoice().start_date_orig(model.invoice().start_date());
2015-10-23 13:55:18 +02:00
@if ($invoice->id)
2015-10-22 20:48:12 +02:00
var invitationContactIds = {!! json_encode($invitationContactIds) !!};
var client = clientMap[invoice.client.public_id];
if (client) { // in case it's deleted
for (var i=0; i<client.contacts.length; i++) {
var contact = client.contacts[i];
contact.send_invoice = invitationContactIds.indexOf(contact.public_id) >= 0;
}
}
model.invoice().addItem(); // add blank item
@else
// set the default account tax rate
@if ($account->invoice_taxes)
@if (! empty($account->tax_name1))
model.invoice().tax_rate1("{{ $account->tax_rate1 }}");
2017-10-31 09:11:49 +01:00
model.invoice().tax_name1("{!! addslashes($account->tax_name1) !!}");
@endif
@if (! empty($account->tax_name2))
model.invoice().tax_rate2("{{ $account->tax_rate2 }}");
2017-10-31 09:11:49 +01:00
model.invoice().tax_name2("{!! addslashes($account->tax_name2) !!}");
@endif
2015-10-22 20:48:12 +02:00
@endif
2017-08-15 17:36:17 +02:00
// load previous isAmountDiscount setting
if (isStorageSupported()) {
var lastIsAmountDiscount = parseInt(localStorage.getItem('last:is_amount_discount'));
if (lastIsAmountDiscount) {
model.invoice().is_amount_discount(lastIsAmountDiscount);
}
}
2015-10-22 20:48:12 +02:00
@endif
2018-03-06 19:21:32 +01:00
@if (isset($tasks) && count($tasks))
2017-05-14 19:22:26 +02:00
var tasks = {!! json_encode($tasks) !!};
2015-10-22 20:48:12 +02:00
for (var i=0; i<tasks.length; i++) {
2015-12-13 21:12:54 +01:00
var task = tasks[i];
2017-07-27 09:08:36 +02:00
var item = model.invoice().addItem(true);
2015-10-22 20:48:12 +02:00
item.notes(task.description);
item.qty(task.duration);
item.cost(task.cost);
2015-10-22 20:48:12 +02:00
item.task_public_id(task.publicId);
2015-12-13 21:12:54 +01:00
}
2015-10-22 20:48:12 +02:00
model.invoice().has_tasks(true);
2017-11-03 09:19:03 +01:00
NINJA.formIsChanged = true;
2015-12-13 21:12:54 +01:00
@endif
2016-01-10 11:25:05 +01:00
2018-03-06 19:21:32 +01:00
@if (isset($expenses) && $expenses->count())
2016-04-11 10:44:53 +02:00
model.expense_currency_id({{ isset($expenseCurrencyId) ? $expenseCurrencyId : 0 }});
2016-01-10 11:25:05 +01:00
// move the blank invoice line item to the end
2017-07-27 09:08:36 +02:00
var blank = model.invoice().invoice_items_without_tasks.pop();
2017-05-08 21:10:39 +02:00
var expenses = {!! $expenses !!}
2016-01-10 11:25:05 +01:00
for (var i=0; i<expenses.length; i++) {
var expense = expenses[i];
var item = model.invoice().addItem();
2016-08-21 17:25:35 +02:00
item.product_key(expense.expense_category ? expense.expense_category.name : '');
item.notes(expense.public_notes);
item.qty(1);
2016-08-21 17:25:35 +02:00
item.expense_public_id(expense.public_id);
item.cost(expense.converted_amount);
item.tax_rate1(expense.tax_rate1);
item.tax_name1(expense.tax_name1);
item.tax_rate2(expense.tax_rate2);
item.tax_name2(expense.tax_name2);
2016-01-10 11:25:05 +01:00
}
2017-07-27 09:08:36 +02:00
model.invoice().invoice_items_without_tasks.push(blank);
2016-01-10 11:25:05 +01:00
model.invoice().has_expenses(true);
2017-11-03 09:19:03 +01:00
NINJA.formIsChanged = true;
2016-08-21 17:25:35 +02:00
@endif
2016-01-10 11:25:05 +01:00
2017-11-03 09:19:03 +01:00
@if ($selectedProducts = session('selectedProducts'))
// move the blank invoice line item to the end
var blank = model.invoice().invoice_items_without_tasks.pop();
var productMap = {};
for (var i=0; i<products.length; i++) {
var product = products[i];
productMap[product.product_key] = product;
}
var selectedProducts = {!! json_encode($selectedProducts) !!}
for (var i=0; i<selectedProducts.length; i++) {
var productKey = selectedProducts[i];
product = productMap[productKey];
if (product) {
var item = model.invoice().addItem();
item.loadData(product);
item.qty(1);
}
}
model.invoice().invoice_items_without_tasks.push(blank);
NINJA.formIsChanged = true;
@endif
2015-10-22 20:48:12 +02:00
@endif
2016-05-15 22:16:08 +02:00
2015-10-22 20:48:12 +02:00
// display blank instead of '0'
if (!NINJA.parseFloat(model.invoice().discount())) model.invoice().discount('');
if (!NINJA.parseFloat(model.invoice().partial())) model.invoice().partial('');
if (!model.invoice().custom_value1()) model.invoice().custom_value1('');
if (!model.invoice().custom_value2()) model.invoice().custom_value2('');
ko.applyBindings(model);
2016-10-25 19:27:24 +02:00
onItemChange(true);
2016-01-10 11:25:05 +01:00
$('#client\\[country_id\\]').on('change', function(e) {
var countryId = $(e.currentTarget).val();
var country = _.findWhere(countries, {id: parseInt(countryId)});
2015-09-07 11:07:55 +02:00
if (country) {
model.invoice().client().country = country;
model.invoice().client().country_id(countryId);
} else {
2014-03-17 19:05:01 +01:00
model.invoice().client().country = false;
model.invoice().client().country_id(0);
}
});
2015-06-03 19:55:48 +02:00
$('[rel=tooltip]').tooltip({'trigger':'manual'});
2013-12-05 21:25:20 +01:00
2017-10-25 23:35:38 +02:00
$('#invoice_date, #due_date, #start_date, #end_date, #last_sent_date, #partial_due_date').datepicker();
2013-11-28 17:40:13 +01:00
2015-10-23 13:55:18 +02:00
@if ($invoice->client && !$invoice->id)
$('input[name=client]').val({{ $invoice->client->public_id }});
2013-12-29 18:40:11 +01:00
@endif
2016-01-10 11:25:05 +01:00
2013-11-26 13:45:07 +01:00
var $input = $('select#client');
2013-12-31 17:38:49 +01:00
$input.combobox().on('change', function(e) {
2015-12-29 08:52:02 +01:00
var oldId = model.invoice().client().public_id();
var clientId = parseInt($('input[name=client]').val(), 10) || 0;
2016-01-10 11:25:05 +01:00
if (clientId > 0) {
2015-10-22 20:48:12 +02:00
var selected = clientMap[clientId];
model.loadClient(selected);
2016-01-10 11:25:05 +01:00
// we enable searching by contact but the selection must be the client
2015-10-22 20:48:12 +02:00
$('.client-input').val(getClientDisplayName(selected));
// if there's an invoice number pattern we'll apply it now
2015-10-23 14:54:07 +02:00
setInvoiceNumber(selected);
2015-12-29 11:23:50 +01:00
refreshPDF(true);
2015-12-29 08:52:02 +01:00
} else if (oldId) {
2014-01-02 09:27:48 +01:00
model.loadClient($.parseJSON(ko.toJSON(new ClientModel())));
2015-10-22 20:48:12 +02:00
model.invoice().client().country = false;
2015-12-29 11:23:50 +01:00
refreshPDF(true);
2015-10-22 20:48:12 +02:00
}
2014-07-07 08:43:16 +02:00
});
// If no clients exists show the client form when clicking on the client select input
if (clients.length === 0) {
$('.client_select input.form-control').on('click', function() {
model.showClientForm();
});
2016-01-10 11:25:05 +01:00
}
2013-11-26 13:45:07 +01:00
2017-10-25 23:35:38 +02:00
$('#invoice_footer, #terms, #public_notes, #invoice_number, #invoice_date, #due_date, #partial_due_date, #start_date, #po_number, #discount, #currency_id, #invoice_design_id, #recurring, #is_amount_discount, #partial, #custom_text_value1, #custom_text_value2').change(function() {
$('#downloadPdfButton').attr('disabled', true);
2015-12-29 08:52:02 +01:00
setTimeout(function() {
2015-07-21 20:51:56 +02:00
refreshPDF(true);
2014-05-04 11:11:08 +02:00
}, 1);
2013-12-30 21:17:45 +01:00
});
2013-12-24 22:27:36 +01:00
$('.frequency_id .input-group-addon').click(function() {
showLearnMore();
});
$('.recurring_due_date .input-group-addon').click(function() {
showRecurringDueDateLearnMore();
});
var fields = ['invoice_date', 'due_date', 'start_date', 'end_date', 'last_sent_date'];
for (var i=0; i<fields.length; i++) {
var field = fields[i];
(function (_field) {
$('.' + _field + ' .input-group-addon').click(function() {
toggleDatePicker(_field);
2016-01-10 11:25:05 +01:00
});
})(field);
}
if (model.invoice().client().public_id() || {{ $invoice->id || count($clients) == 0 ? '1' : '0' }}) {
// do nothing
} else {
$('.client_select input.form-control').focus();
}
2016-01-10 11:25:05 +01:00
2013-12-29 00:33:48 +01:00
$('#clientModal').on('shown.bs.modal', function () {
2015-11-02 23:05:28 +01:00
$('#client\\[name\\]').focus();
2013-12-29 00:33:48 +01:00
}).on('hidden.bs.modal', function () {
2013-12-17 14:14:47 +01:00
if (model.clientBackup) {
model.loadClient(model.clientBackup);
2015-07-21 20:51:56 +02:00
refreshPDF(true);
2013-12-17 14:14:47 +01:00
}
2013-11-26 13:45:07 +01:00
})
2016-01-10 11:25:05 +01:00
2014-01-02 18:16:00 +01:00
$('#relatedActions > button:first').click(function() {
2014-01-15 15:01:24 +01:00
onPaymentClick();
2014-01-02 18:16:00 +01:00
});
2013-12-10 23:10:43 +01:00
$('label.radio').addClass('radio-inline');
2016-01-10 11:25:05 +01:00
2015-10-23 13:55:18 +02:00
@if ($invoice->client->id)
2014-01-06 19:03:00 +01:00
$input.trigger('change');
2016-01-10 11:25:05 +01:00
@else
2015-07-21 20:51:56 +02:00
refreshPDF(true);
2014-01-06 19:03:00 +01:00
@endif
2014-01-02 00:12:33 +01:00
var client = model.invoice().client();
2016-01-10 11:25:05 +01:00
setComboboxValue($('.client_select'),
client.public_id(),
client.name.display());
2015-07-12 21:43:45 +02:00
@if (isset($tasks) && $tasks)
NINJA.formIsChanged = true;
@endif
2015-12-29 08:52:02 +01:00
2016-01-10 11:25:05 +01:00
@if (isset($expenses) && $expenses)
NINJA.formIsChanged = true;
@endif
2015-12-29 08:52:02 +01:00
applyComboboxListeners();
2016-05-15 22:16:08 +02:00
@if (Auth::user()->account->hasFeature(FEATURE_DOCUMENTS))
$('.main-form').submit(function(){
if($('#document-upload .dropzone .fallback input').val())$(this).attr('enctype', 'multipart/form-data')
else $(this).removeAttr('enctype')
})
2016-05-15 22:16:08 +02:00
2016-03-23 03:23:45 +01:00
// Initialize document upload
2016-05-25 10:59:46 +02:00
window.dropzone = false;
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
if (window.dropzone) {
return;
}
var target = $(e.target).attr('href') // activated tab
if (target != '#attached-documents') {
return;
}
2017-07-20 21:45:10 +02:00
@include('partials.dropzone', ['documentSource' => 'model.invoice().documents()'])
2016-05-25 10:59:46 +02:00
});
2016-03-23 03:59:20 +01:00
@endif
2016-01-10 11:25:05 +01:00
});
2016-01-11 20:41:02 +01:00
function onFrequencyChange(){
var currentName = $('#frequency_id').find('option:selected').text()
var currentDueDateNumber = $('#recurring_due_date').find('option:selected').attr('data-num');
var optionClass = currentName && currentName.toLowerCase().indexOf('week') > -1 ? 'weekly' : 'monthly';
var replacementOption = $('#recurring_due_date option[data-num=' + currentDueDateNumber + '].' + optionClass);
2016-01-11 20:41:02 +01:00
$('#recurring_due_date option').hide();
$('#recurring_due_date option.' + optionClass).show();
2016-01-11 20:41:02 +01:00
// Switch to an equivalent option
if(replacementOption.length){
replacementOption.attr('selected','selected');
}
else{
$('#recurring_due_date').val('');
}
}
2013-11-26 13:45:07 +01:00
function applyComboboxListeners() {
2015-12-29 20:05:08 +01:00
var selectorStr = '.invoice-table input, .invoice-table textarea';
2015-12-29 08:52:02 +01:00
$(selectorStr).off('change').on('change', function(event) {
if ($(event.target).hasClass('handled')) {
return;
}
$('#downloadPdfButton').attr('disabled', true);
2015-12-29 08:52:02 +01:00
onItemChange();
refreshPDF(true);
2013-12-31 10:43:39 +01:00
});
2015-12-29 20:05:08 +01:00
var selectorStr = '.invoice-table select';
$(selectorStr).off('blur').on('blur', function(event) {
onItemChange();
refreshPDF(true);
});
2016-10-30 12:28:01 +01:00
$('textarea.word-wrap').on('keyup focus', function(e) {
2016-09-18 21:12:09 +02:00
$(this).height(0).height(this.scrollHeight-18);
2015-09-29 20:19:18 +02:00
});
2016-09-18 21:12:09 +02:00
}
2013-11-26 13:45:07 +01:00
function createInvoiceModel() {
var model = ko.toJS(window.model);
2018-02-15 09:29:45 +01:00
if (! model) {
return;
}
var invoice = model.invoice;
invoice.features = {
customize_invoice_design:{{ Auth::user()->hasFeature(FEATURE_CUSTOMIZE_INVOICE_DESIGN) ? 'true' : 'false' }},
remove_created_by:{{ Auth::user()->hasFeature(FEATURE_REMOVE_CREATED_BY) ? 'true' : 'false' }},
invoice_settings:{{ Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS) ? 'true' : 'false' }}
};
2015-11-08 21:34:26 +01:00
invoice.is_quote = {{ $entityType == ENTITY_QUOTE ? 'true' : 'false' }};
2014-12-03 23:05:38 +01:00
invoice.contact = _.findWhere(invoice.client.contacts, {send_invoice: true});
2014-04-13 15:34:58 +02:00
if (invoice.is_recurring) {
2017-07-26 11:26:16 +02:00
invoice.invoice_number = "{!! trans('texts.assigned_when_sent') !!}";
2015-10-22 20:48:12 +02:00
if (invoice.start_date) {
invoice.invoice_date = invoice.start_date;
}
}
2017-02-01 10:19:29 +01:00
@if (!$invoice->id || $invoice->is_recurring)
2015-04-27 14:28:40 +02:00
if (!invoice.terms) {
2015-12-17 09:19:56 +01:00
invoice.terms = account['{{ $entityType }}_terms'];
2015-04-27 14:28:40 +02:00
}
if (!invoice.invoice_footer) {
2015-12-17 09:19:56 +01:00
invoice.invoice_footer = account['invoice_footer'];
2015-04-27 14:28:40 +02:00
}
@endif
2015-02-28 22:42:47 +01:00
2016-01-18 15:09:06 +01:00
@if ($account->hasLogo())
invoice.image = "{{ Form::image_data($account->getLogoRaw(), true) }}";
2014-03-18 22:25:54 +01:00
invoice.imageWidth = {{ $account->getLogoWidth() }};
invoice.imageHeight = {{ $account->getLogoHeight() }};
@endif
2014-02-21 06:26:40 +01:00
2018-02-15 09:29:45 +01:00
if (! invoice.public_id || NINJA.formIsChanged) {
2018-02-16 10:07:58 +01:00
invoice.watermark = "{{ strtoupper(trans('texts.preview')) }}";
2018-02-15 09:29:45 +01:00
}
2015-04-13 14:49:40 +02:00
return invoice;
2013-11-26 13:45:07 +01:00
}
var origInvoiceNumber = false;
2015-07-21 20:51:56 +02:00
function getPDFString(cb, force) {
@if (! $invoice->id && $account->credit_number_counter > 0)
var total = model.invoice().totals.rawTotal();
var invoiceNumber = model.invoice().invoice_number();
var creditNumber = "{{ $account->getNextNumber(new \App\Models\Credit()) }}";
if (total < 0 && invoiceNumber != creditNumber) {
origInvoiceNumber = invoiceNumber;
model.invoice().invoice_number(creditNumber);
} else if (total >= 0 && invoiceNumber == creditNumber && origInvoiceNumber) {
model.invoice().invoice_number(origInvoiceNumber);
}
@endif
2017-01-25 19:19:32 +01:00
@if ( ! $account->live_preview)
return;
@endif
2017-09-03 20:10:11 +02:00
2018-02-19 15:31:33 +01:00
var invoice = createInvoiceModel();
var design = getDesignJavascript();
2017-10-17 10:09:22 +02:00
if (! design) {
return;
}
2017-09-03 20:10:11 +02:00
2015-07-21 20:51:56 +02:00
generatePDF(invoice, design, force, cb);
2014-03-10 12:04:15 +01:00
}
2014-04-14 13:33:43 +02:00
2014-10-12 20:11:41 +02:00
function getDesignJavascript() {
var id = $('#invoice_design_id').val();
if (id == '-1') {
showMoreDesigns();
2014-10-25 19:32:28 +02:00
model.invoice().invoice_design_id(1);
return invoiceDesigns[0].javascript;
} else {
2015-07-21 20:51:56 +02:00
var design = _.find(invoiceDesigns, function(design){ return design.id == id});
return design ? design.javascript : '';
}
2013-12-07 19:45:00 +01:00
}
2013-11-26 13:45:07 +01:00
2015-09-07 11:07:55 +02:00
function resetTerms() {
2016-07-28 18:55:23 +02:00
sweetConfirm(function() {
2015-09-17 21:01:06 +02:00
model.invoice().terms(model.invoice().default_terms());
refreshPDF();
2016-07-28 18:55:23 +02:00
});
2015-09-07 11:07:55 +02:00
return false;
}
function resetFooter() {
2016-07-28 18:55:23 +02:00
sweetConfirm(function() {
2015-09-17 21:01:06 +02:00
model.invoice().invoice_footer(model.invoice().default_footer());
refreshPDF();
2016-07-28 18:55:23 +02:00
});
2015-09-07 11:07:55 +02:00
return false;
}
2013-11-26 13:45:07 +01:00
function onDownloadClick() {
2015-06-01 15:06:18 +02:00
trackEvent('/activity', '/download_pdf');
2013-11-26 13:45:07 +01:00
var invoice = createInvoiceModel();
2015-10-23 13:55:18 +02:00
var design = getDesignJavascript();
if (!design) return;
var doc = generatePDF(invoice, design, true);
2017-06-05 15:46:44 +02:00
var type = invoice.is_quote ? '{!! trans('texts.'.ENTITY_QUOTE) !!}' : '{!! trans('texts.'.ENTITY_INVOICE) !!}';
2017-05-08 10:18:35 +02:00
doc.save(type + '-' + $('#invoice_number').val() + '.pdf');
2013-11-26 13:45:07 +01:00
}
2016-09-26 08:54:59 +02:00
function onRecurrClick() {
var invoice = model.invoice();
if (invoice.is_recurring()) {
var recurring = false;
var enableLabel = "{{ trans('texts.enable_recurring')}}";
var actionLabel = "{{ trans('texts.mark_sent') }}";
2016-09-26 08:54:59 +02:00
} else {
var recurring = true;
var enableLabel = "{{ trans('texts.disable_recurring')}}";
var actionLabel = "{{ trans('texts.mark_active') }}";
2016-09-26 08:54:59 +02:00
}
invoice.is_recurring(recurring);
$('#recurrButton').html(enableLabel + "<span class='glyphicon glyphicon-repeat'></span>");
$('#saveButton').html(actionLabel + "<span class='glyphicon glyphicon-globe'></span>");
2016-09-26 08:54:59 +02:00
}
function onAddItemClick() {
model.forceShowItems(true);
$('#addItemButton').hide();
}
2013-11-26 13:45:07 +01:00
function onEmailClick() {
if (!NINJA.isRegistered) {
2016-07-28 18:55:23 +02:00
swal("{!! trans('texts.registration_required') !!}");
return;
}
var clientId = parseInt($('input[name=client]').val(), 10) || 0;
if (clientId == 0 ) {
swal("{!! trans('texts.no_client_selected') !!}");
return;
}
if (!isContactSelected()) {
swal("{!! trans('texts.no_contact_selected') !!}");
return;
}
if (!isEmailValid()) {
2016-07-28 18:55:23 +02:00
swal("{!! trans('texts.provide_email') !!}");
2015-07-07 22:08:16 +02:00
return;
}
2015-07-07 22:08:16 +02:00
if (model.invoice().is_recurring()) {
sweetConfirm(function() {
onConfirmEmailClick();
}, getSendToEmails());
} else {
showEmailModal();
}
2013-11-26 13:45:07 +01:00
}
2017-02-05 08:53:49 +01:00
function onConfirmEmailClick() {
2017-02-06 10:41:16 +01:00
$('#emailModal div.modal-footer button').attr('disabled', true);
2017-02-05 08:53:49 +01:00
model.invoice().is_public(true);
2017-02-21 12:06:45 +01:00
submitAction('email');
2017-02-05 08:53:49 +01:00
}
function onSaveDraftClick() {
model.invoice().is_public(false);
onSaveClick();
}
function onMarkSentClick() {
if (model.invoice().is_recurring()) {
if (! model.invoice().start_date()) {
swal("{{ trans('texts.start_date_required') }}");
return false;
}
if (!isSaveValid()) {
model.showClientForm();
return false;
}
var title = "{!! trans("texts.confirm_recurring_email_invoice") !!}";
var text = '\n' + getSendToEmails();
var startDate = moment($('#start_date').datepicker('getDate'));
// warn invoice will be emailed when saving new recurring invoice
2017-06-13 14:25:56 +02:00
if (model.invoice().start_date() == "{{ Utils::fromSqlDate(date('Y-m-d')) }}") {
text += '\n\n' + "{!! trans("texts.confirm_recurring_timing") !!}";
// check if the start date is in the future
} else if (startDate.isAfter(moment(), 'day')) {
var message = "{!! trans("texts.email_will_be_sent_on") !!}";
text += '\n\n' + message.replace(':date', model.invoice().start_date());
2017-06-13 14:25:56 +02:00
}
sweetConfirm(function() {
model.invoice().is_public(true);
submitAction('');
}, text, title);
return;
} else {
model.invoice().is_public(true);
onSaveClick();
}
}
function onSaveClick() {
@if ($invoice->id)
if (model.invoice().is_recurring()) {
if (model.invoice().start_date() != model.invoice().start_date_orig()) {
var text = "{!! trans("texts.original_start_date") !!}: " + model.invoice().start_date_orig() + '\n'
+ "{!! trans("texts.new_start_date") !!}: " + model.invoice().start_date();
var title = "{!! trans("texts.warn_start_date_changed") !!}";
sweetConfirm(function() {
submitAction('');
}, text, title);
return;
}
}
@endif
2016-07-28 18:55:23 +02:00
@if (!empty($autoBillChangeWarning))
var text = "{!! trans('texts.warn_change_auto_bill') !!}";
sweetConfirm(function() {
submitAction('');
}, text);
return;
@endif
submitAction('');
}
2014-07-30 09:08:01 +02:00
2015-07-07 22:08:16 +02:00
function getSendToEmails() {
var client = model.invoice().client();
var parts = [];
for (var i=0; i<client.contacts().length; i++) {
var contact = client.contacts()[i];
if (contact.send_invoice()) {
parts.push(contact.displayName());
}
2015-12-29 08:52:02 +01:00
}
2015-07-07 22:08:16 +02:00
return parts.join('\n');
}
2015-04-22 23:40:21 +02:00
function preparePdfData(action) {
var invoice = createInvoiceModel();
2015-12-29 08:52:02 +01:00
var design = getDesignJavascript();
2015-04-22 23:40:21 +02:00
if (!design) return;
2016-01-10 11:25:05 +01:00
2015-04-22 23:40:21 +02:00
doc = generatePDF(invoice, design, true);
doc.getDataUrl( function(pdfString){
2015-09-17 21:01:06 +02:00
$('#pdfupload').val(pdfString);
submitAction(action);
});
2015-04-22 23:40:21 +02:00
}
2014-07-30 09:08:01 +02:00
function submitAction(value) {
2017-03-26 12:19:07 +02:00
if (!isSaveValid()) {
model.showClientForm();
return false;
}
$('#action').val(value);
$('#submitButton').click();
}
function onFormSubmit(event) {
if (window.countUploadingDocuments > 0) {
2016-07-28 18:55:23 +02:00
swal("{!! trans('texts.wait_for_upload') !!}");
return false;
}
@if ($invoice->is_deleted || $invoice->isClientTrashed())
2016-10-06 12:02:25 +02:00
if ($('#bulk_action').val() != 'restore') {
return false;
}
2016-10-06 10:05:04 +02:00
@endif
// check invoice number is unique
if ($('.invoice-number').hasClass('has-error')) {
return false;
2016-09-21 16:07:01 +02:00
} else if ($('.partial').hasClass('has-error')) {
return false;
}
if (!isSaveValid()) {
model.showClientForm();
return false;
}
// check currency matches for expenses
var expenseCurrencyId = model.expense_currency_id();
var clientCurrencyId = model.invoice().client().currency_id() || {{ $account->getCurrencyId() }};
if (expenseCurrencyId && expenseCurrencyId != clientCurrencyId) {
2016-07-28 18:55:23 +02:00
swal("{!! trans('texts.expense_error_mismatch_currencies') !!}");
return false;
}
@if (Auth::user()->canCreateOrEdit(ENTITY_INVOICE, $invoice))
2018-02-21 14:36:00 +01:00
if (NINJA.formIsSubmitted) {
return false;
}
NINJA.formIsSubmitted = true;
$('#saveButton, #emailButton, #draftButton').attr('disabled', true);
// if save fails ensure user can try again
$.post('{{ url($url) }}', $('.main-form').serialize(), function(data) {
2017-03-22 21:45:47 +01:00
if (data && data.indexOf('http') === 0) {
2017-03-21 10:08:57 +01:00
NINJA.formIsChanged = false;
location.href = data;
} else {
handleSaveFailed();
}
}).fail(function(data) {
2017-03-21 10:08:57 +01:00
handleSaveFailed(data);
});
return false;
@else
return false;
@endif
}
2017-03-21 10:08:57 +01:00
function handleSaveFailed(data) {
$('#saveButton, #emailButton, #draftButton').attr('disabled', false);
$('#emailModal div.modal-footer button').attr('disabled', false);
2018-02-21 14:36:00 +01:00
NINJA.formIsSubmitted = false;
2017-03-21 10:08:57 +01:00
var error = '';
if (data) {
var error = firstJSONError(data.responseJSON) || data.statusText;
}
swal("{!! trans('texts.invoice_save_error') !!}", error);
}
2015-10-28 20:22:07 +01:00
function submitBulkAction(value) {
$('#bulk_action').val(value);
$('.bulkForm')[0].submit();
2015-10-28 20:22:07 +01:00
}
2014-03-09 22:19:56 +01:00
function isSaveValid() {
var isValid = model.invoice().client().name() ? true : false;
2014-07-30 09:08:01 +02:00
for (var i=0; i<model.invoice().client().contacts().length; i++) {
var contact = model.invoice().client().contacts()[i];
2017-07-02 19:55:21 +02:00
var email = contact.email() ? contact.email().trim() : '';
if (isValidEmailAddress(email) || contact.first_name() || contact.last_name()) {
2014-03-09 22:19:56 +01:00
isValid = true;
break;
}
}
return isValid;
}
2016-01-10 11:25:05 +01:00
function isContactSelected() {
var sendTo = false;
var client = model.invoice().client();
for (var i=0; i<client.contacts().length; i++) {
var contact = client.contacts()[i];
if (contact.send_invoice()) {
return true;
}
}
return false;
}
2014-03-09 22:19:56 +01:00
function isEmailValid() {
2015-11-16 20:21:48 +01:00
var isValid = true;
var client = model.invoice().client();
2014-03-09 22:19:56 +01:00
for (var i=0; i<client.contacts().length; i++) {
2015-11-16 20:21:48 +01:00
var contact = client.contacts()[i];
if ( ! contact.send_invoice()) {
continue;
}
2017-07-02 19:55:21 +02:00
var email = contact.email() ? contact.email().trim() : '';
if (isValidEmailAddress(email)) {
2014-03-09 22:19:56 +01:00
isValid = true;
} else {
isValid = false;
break;
}
}
return isValid;
2014-03-09 22:19:56 +01:00
}
function onCloneInvoiceClick() {
submitAction('clone_invoice');
}
function onCloneQuoteClick() {
submitAction('clone_quote');
2013-12-11 21:33:44 +01:00
}
2014-05-20 23:40:09 +02:00
function onConvertClick() {
2016-01-10 11:25:05 +01:00
submitAction('convert');
2014-05-20 23:40:09 +02:00
}
2015-10-23 13:55:18 +02:00
@if ($invoice->id)
function onPaymentClick() {
2016-07-28 18:55:23 +02:00
@if (!empty($autoBillChangeWarning))
sweetConfirm(function() {
window.location = '{{ URL::to('payments/create/' . $invoice->client->public_id . '/' . $invoice->public_id ) }}';
}, "{!! trans('texts.warn_change_auto_bill') !!}");
@else
window.location = '{{ URL::to('payments/create/' . $invoice->client->public_id . '/' . $invoice->public_id ) }}';
@endif
2015-10-23 13:55:18 +02:00
}
2014-01-02 14:21:15 +01:00
2015-10-23 13:55:18 +02:00
function onCreditClick() {
window.location = '{{ URL::to('credits/create/' . $invoice->client->public_id . '/' . $invoice->public_id ) }}';
}
@endif
2016-01-10 11:25:05 +01:00
2013-12-03 18:32:33 +01:00
function onArchiveClick() {
2015-10-28 20:22:07 +01:00
submitBulkAction('archive');
2013-12-03 18:32:33 +01:00
}
function onDeleteClick() {
2016-07-28 18:55:23 +02:00
sweetConfirm(function() {
submitBulkAction('delete');
});
2013-12-03 18:32:33 +01:00
}
function formEnterClick(event) {
if (event.keyCode === 13){
if (event.target.type == 'textarea') {
return;
2013-12-11 21:33:44 +01:00
}
2015-10-25 08:13:06 +01:00
event.preventDefault();
2014-01-02 00:12:33 +01:00
2015-10-25 08:13:06 +01:00
@if($invoice->trashed())
return;
@endif
submitAction('');
return false;
2013-11-26 13:45:07 +01:00
}
}
2013-12-05 21:25:20 +01:00
2016-01-10 11:25:05 +01:00
function clientModalEnterClick(event) {
2013-11-26 13:45:07 +01:00
if (event.keyCode === 13){
2016-01-10 11:25:05 +01:00
event.preventDefault();
model.clientFormComplete();
2013-11-26 13:45:07 +01:00
return false;
}
}
2016-10-25 19:27:24 +02:00
function onItemChange(silent)
2013-12-01 13:22:08 +01:00
{
var hasEmptyStandard = false;
var hasEmptyTask = false;
2017-07-27 09:08:36 +02:00
for (var i=0; i<model.invoice().invoice_items_without_tasks().length; i++) {
var item = model.invoice().invoice_items_without_tasks()[i];
2013-12-01 13:22:08 +01:00
if (item.isEmpty()) {
2017-07-27 09:08:36 +02:00
hasEmptyStandard = true;
2013-12-01 13:22:08 +01:00
}
}
if (!hasEmptyStandard) {
2014-01-01 18:34:37 +01:00
model.invoice().addItem();
2013-12-01 13:22:08 +01:00
}
2017-07-27 09:08:36 +02:00
for (var i=0; i<model.invoice().invoice_items_with_tasks().length; i++) {
var item = model.invoice().invoice_items_with_tasks()[i];
if (item.isEmpty()) {
hasEmptyTask = true;
}
}
if (!hasEmptyTask) {
2017-07-27 09:08:36 +02:00
model.invoice().addItem(true);
}
2016-10-25 19:27:24 +02:00
if (!silent) {
NINJA.formIsChanged = true;
}
2013-11-26 13:45:07 +01:00
}
2016-09-21 16:07:01 +02:00
function onPartialChange()
2015-04-16 19:12:56 +02:00
{
2015-04-16 21:57:12 +02:00
var val = NINJA.parseFloat($('#partial').val());
2015-06-03 19:55:48 +02:00
var oldVal = val;
2015-04-16 21:57:12 +02:00
val = Math.max(Math.min(val, model.invoice().totals.rawTotal()), 0);
2016-01-10 11:25:05 +01:00
2016-09-21 16:07:01 +02:00
if (val != oldVal) {
if ($('.partial').hasClass('has-error')) {
return;
}
$('.partial')
.addClass('has-error')
.find('div.partial')
2016-09-21 16:07:01 +02:00
.append('<span class="help-block">{{ trans('texts.partial_value') }}</span>');
} else {
$('.partial')
.removeClass('has-error')
.find('span')
.hide();
2015-06-03 19:55:48 +02:00
}
2016-09-21 16:07:01 +02:00
2015-04-16 19:12:56 +02:00
}
function onRecurringEnabled()
2015-03-02 15:17:33 +01:00
{
if ($('#recurring').prop('checked')) {
2015-08-20 17:09:04 +02:00
$('#emailButton').attr('disabled', true);
2015-04-16 19:12:56 +02:00
model.invoice().partial('');
2015-03-02 15:17:33 +01:00
} else {
2015-08-20 17:09:04 +02:00
$('#emailButton').removeAttr('disabled');
2015-03-02 15:17:33 +01:00
}
}
2015-10-22 20:48:12 +02:00
function showLearnMore() {
2015-10-25 08:13:06 +01:00
$('#recurringModal').modal('show');
2015-10-22 20:48:12 +02:00
}
2014-01-01 18:34:37 +01:00
function showRecurringDueDateLearnMore() {
$('#recurringDueDateModal').modal('show');
}
2015-10-22 20:48:12 +02:00
function setInvoiceNumber(client) {
2017-03-29 10:46:52 +02:00
@if ($invoice->id || !$account->hasClientNumberPattern($invoice))
2015-10-22 20:48:12 +02:00
return;
@endif
2017-01-04 09:11:32 +01:00
var number = '{{ $account->applyNumberPattern($invoice) }}';
2017-03-29 10:46:52 +02:00
number = number.replace('{$clientCustom1}', client.custom_value1 ? client.custom_value1 : '');
number = number.replace('{$clientCustom2}', client.custom_value2 ? client.custom_value1 : '');
number = number.replace('{$clientIdNumber}', client.id_number ? client.id_number : '');
2017-04-02 19:35:10 +02:00
@if ($invoice->isQuote() && ! $account->share_counter)
number = number.replace('{$clientCounter}', pad(client.quote_number_counter, {{ $account->invoice_number_padding }}));
@else
number = number.replace('{$clientCounter}', pad(client.invoice_number_counter, {{ $account->invoice_number_padding }}));
@endif
2017-03-29 10:46:52 +02:00
// backwards compatibility
number = number.replace('{$custom1}', client.custom_value1 ? client.custom_value1 : '');
2015-12-23 12:49:49 +01:00
number = number.replace('{$custom2}', client.custom_value2 ? client.custom_value1 : '');
number = number.replace('{$idNumber}', client.id_number ? client.id_number : '');
2015-10-22 20:48:12 +02:00
model.invoice().invoice_number(number);
}
2016-05-15 22:16:08 +02:00
2017-07-20 21:45:10 +02:00
function addDocument(file) {
file.index = model.invoice().documents().length;
model.invoice().addDocument({name:file.name, size:file.size, type:file.type});
}
2017-07-20 21:45:10 +02:00
function addedDocument(file, response) {
model.invoice().documents()[file.index].update(response.document);
@if ($account->invoice_embed_documents)
refreshPDF(true);
@endif
}
2016-05-29 17:42:36 +02:00
2017-07-20 21:45:10 +02:00
function deleteDocument(file) {
model.invoice().removeDocument(file.public_id);
refreshPDF(true);
}
2014-01-01 18:34:37 +01:00
2013-11-26 13:45:07 +01:00
</script>
@if ($account->hasFeature(FEATURE_DOCUMENTS) && $account->invoice_embed_documents)
2016-03-23 23:40:42 +01:00
@foreach ($invoice->documents as $document)
@if($document->isPDFEmbeddable())
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
@endif
2016-03-23 23:40:42 +01:00
@endforeach
@foreach ($invoice->expenses as $expense)
@foreach ($expense->documents as $document)
@if($document->isPDFEmbeddable())
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
@endif
@endforeach
@endforeach
2016-03-23 23:40:42 +01:00
@endif
2013-11-26 13:45:07 +01:00
2015-11-09 10:50:47 +01:00
@stop