2013-11-26 13:45:07 +01:00
@ extends ( 'header' )
2013-12-08 14:32:49 +01:00
@ section ( 'head' )
@ parent
< script type = " text/javascript " src = " { { asset('js/pdf_viewer.js') }} " ></ script >
< script type = " text/javascript " src = " { { asset('js/compatibility.js') }} " ></ script >
@ stop
2013-11-26 13:45:07 +01:00
@ section ( 'content' )
2013-12-07 19:45:00 +01:00
2013-11-26 13:45:07 +01:00
< p >& nbsp ; </ p >
2013-11-26 22:45:10 +01:00
{{ Former :: open ( $url ) -> method ( $method ) -> addClass ( 'main_form' ) -> rules ( array (
2013-12-08 14:32:49 +01:00
'client' => 'required' ,
2013-12-30 21:17:45 +01:00
'email' => 'required' ,
2013-12-10 23:10:43 +01:00
'product_key' => 'max:14' ,
2013-11-26 22:45:10 +01:00
)); }}
2013-12-13 10:13:57 +01:00
< div class = " row " style = " min-height:195px " onkeypress = " formEnterClick(event) " >
2013-12-24 07:22:16 +01:00
< div class = " col-md-5 " id = " col_1 " >
2013-12-30 21:17:45 +01:00
{{ Former :: select ( 'client' ) -> addOption ( '' , '' ) -> data_bind ( " dropdown: client " )
2013-12-13 10:13:57 +01:00
-> 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 " >
2013-12-13 10:13:57 +01:00
< a href = " # " data - bind = " click: showClientForm, text: showClientText " ></ a >
</ div >
</ div >
< div data - bind = " with: client " >
< div class = " form-group " data - bind = " visible: contacts().length > 1, foreach: contacts " >
< div class = " col-lg-8 col-lg-offset-4 " >
< label for = " test " class = " checkbox " data - bind = " attr: { for: $index () + '_check'} " >
< input type = " checkbox " value = " 1 " data - bind = " checked: send_invoice, attr: { id: $index () + '_check'} " >
< span data - bind = " text: fullName " />
</ label >
</ div >
</ div >
</ div >
2013-12-15 13:55:50 +01:00
{{ Former :: textarea ( 'terms' ) -> data_bind ( " value: wrapped_terms, valueUpdate: 'afterkeydown' " ) }}
2013-12-30 21:17:45 +01:00
{{ Former :: textarea ( 'public_notes' ) -> data_bind ( " value: wrapped_notes, valueUpdate: 'afterkeydown' " ) }}
2013-12-11 21:33:44 +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 " >
2013-12-13 10:13:57 +01:00
< div data - bind = " visible: !is_recurring() " >
{{ Former :: text ( 'invoice_number' ) -> label ( 'Invoice #' ) -> data_bind ( " value: invoice_number, valueUpdate: 'afterkeydown' " ) }}
2013-12-25 22:34:42 +01:00
{{ Former :: text ( 'invoice_date' ) -> data_bind ( " value: invoice_date, valueUpdate: 'afterkeydown' " ) -> data_date_format ( DEFAULT_DATE_PICKER_FORMAT ) }}
{{ Former :: text ( 'due_date' ) -> data_bind ( " value: due_date, valueUpdate: 'afterkeydown' " ) -> data_date_format ( DEFAULT_DATE_PICKER_FORMAT ) }}
2013-12-10 23:10:43 +01:00
</ div >
2013-12-13 10:13:57 +01:00
< div data - bind = " visible: is_recurring " >
{{ Former :: select ( 'frequency_id' ) -> label ( 'How often' ) -> options ( $frequencies ) -> data_bind ( " value: frequency_id " ) }}
2013-12-25 22:34:42 +01:00
{{ Former :: text ( 'start_date' ) -> data_bind ( " value: start_date, valueUpdate: 'afterkeydown' " ) -> data_date_format ( DEFAULT_DATE_PICKER_FORMAT ) }}
{{ Former :: text ( 'end_date' ) -> data_bind ( " value: end_date, valueUpdate: 'afterkeydown' " ) -> data_date_format ( DEFAULT_DATE_PICKER_FORMAT ) }}
2013-12-10 23:10:43 +01:00
</ div >
2013-12-24 07:22:16 +01:00
@ if ( $invoice && $invoice -> recurring_invoice_id )
2013-12-30 21:17:45 +01:00
< div class = " pull-right " style = " padding-top: 6px " >
2013-12-24 07:22:16 +01:00
Created by a {{ link_to ( '/invoices/' . $invoice -> recurring_invoice_id , 'recurring invoice' ) }}
</ div >
2013-12-30 21:17:45 +01:00
@ else
< div data - bind = " visible: invoice_status_id() < CONSTS.INVOICE_STATUS_SENT " >
{{ Former :: checkbox ( 'recurring' ) -> text ( 'Enable | <a href="#" rel="tooltip" data-toggle="tooltip" title="Recurring invoices are automatically sent. Use :MONTH, :QUARTER or :YEAR for dynamic dates. Basic math works as well. ie, :MONTH-1.">Learn more</a>' ) -> data_bind ( " checked: is_recurring " )
-> inlineHelp ( $invoice && $invoice -> last_sent_date ? 'Last invoice sent ' . Utils :: dateToString ( $invoice -> last_sent_date ) : '' ) }}
</ div >
2013-12-24 07:22:16 +01:00
@ endif
2013-12-11 21:33:44 +01:00
2013-11-26 22:45:10 +01:00
</ div >
2013-12-24 07:22:16 +01:00
< div class = " col-md-3 " id = " col_2 " >
{{ Former :: text ( 'po_number' ) -> label ( 'PO number' ) -> data_bind ( " value: po_number, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'discount' ) -> data_bind ( " value: discount, valueUpdate: 'afterkeydown' " ) }}
2013-12-29 18:40:11 +01:00
{{ Former :: select ( 'currency_id' ) -> label ( 'Currency' ) -> fromQuery ( $currencies , 'name' , 'id' ) -> data_bind ( " value: currency_id " ) }}
2013-12-27 10:10:32 +01:00
< div class = " form-group " style = " margin-bottom: 8px " >
< label for = " recurring " class = " control-label col-lg-4 col-sm-4 " > Taxes </ label >
< div class = " col-lg-8 col-sm-8 " style = " padding-top: 7px " >
< a href = " # " data - bind = " click: showTaxesForm " > Manage taxe rates </ a >
</ div >
</ div >
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
2013-11-26 22:45:10 +01:00
< p >& nbsp ; </ p >
2013-11-26 13:45:07 +01:00
2013-12-13 10:13:57 +01:00
{{ Former :: hidden ( 'data' ) -> data_bind ( " value: ko.toJSON(model) " ) }}
2013-11-28 13:15:34 +01:00
2013-11-27 08:38:37 +01:00
< table class = " table invoice-table " style = " margin-bottom: 0px !important " >
2013-11-26 22:45:10 +01:00
< thead >
< tr >
< th class = " hide-border " ></ th >
< th > Item </ th >
< th > Description </ th >
2013-12-13 10:13:57 +01:00
< th > Unit Cost </ th >
< th > Quantity </ th >
2013-12-27 10:10:32 +01:00
< th data - bind = " visible: tax_rates().length > 1 " > Tax </ th >
2013-11-26 22:45:10 +01:00
< th > Line & nbsp ; Total </ th >
< th class = " hide-border " ></ th >
</ tr >
</ thead >
2013-12-13 10:13:57 +01:00
< tbody data - bind = " sortable: { data: invoice_items, afterMove: onDragged } " >
2013-11-26 22:45:10 +01:00
< tr data - bind = " event: { mouseover: showActions, mouseout: hideActions } " class = " sortable-row " >
2013-12-08 14:32:49 +01:00
< td style = " width:20px; " class = " hide-border td-icon " >
2013-12-13 10:13:57 +01:00
< i data - bind = " visible: actionsVisible() && $parent .invoice_items().length > 1 " class = " fa fa-sort " ></ i >
2013-11-26 22:45:10 +01:00
</ td >
2013-12-01 13:22:08 +01:00
< td style = " width:120px " >
2013-12-27 10:10:32 +01:00
{{ Former :: text ( 'product_key' ) -> useDatalist ( Product :: getProductKeys ( $products ), 'key' ) -> onkeyup ( 'onItemChange()' )
2013-11-28 13:15:34 +01:00
-> raw () -> data_bind ( " value: product_key, valueUpdate: 'afterkeydown' " ) -> addClass ( 'datalist' ) }}
2013-11-26 22:45:10 +01:00
</ td >
< td style = " width:300px " >
2013-12-15 13:55:50 +01:00
< textarea data - bind = " value: wrapped_notes, valueUpdate: 'afterkeydown' " rows = " 1 " cols = " 60 " style = " resize: none; " class = " form-control word-wrap " onchange = " refreshPDF() " ></ textarea >
2013-11-26 22:45:10 +01:00
</ td >
< td style = " width:100px " >
2013-12-27 10:10:32 +01:00
< input onkeyup = " onItemChange() " data - bind = " value: cost, valueUpdate: 'afterkeydown' " style = " text-align: right " class = " form-control " onchange = " refreshPDF() " //>
2013-11-26 22:45:10 +01:00
</ td >
< td style = " width:80px " >
2013-12-29 12:28:44 +01:00
< input onkeyup = " onItemChange() " data - bind = " value: prettyQty, valueUpdate: 'afterkeydown' " style = " text-align: right " class = " form-control " onchange = " refreshPDF() " //>
2013-11-26 22:45:10 +01:00
</ td >
2013-12-29 12:28:44 +01:00
< td style = " width:120px; vertical-align:middle " data - bind = " visible: $parent .tax_rates().length > 1 " >
< select class = " form-control " style = " width:100% " data - bind = " value: tax, options: $parent .tax_rates, optionsText: 'displayName' " ></ select >
2013-11-26 22:45:10 +01:00
</ td >
2013-12-27 10:10:32 +01:00
< td style = " width:100px;text-align: right;padding-top:9px !important " >
2013-11-26 22:45:10 +01:00
< span data - bind = " text: total " ></ span >
</ td >
2013-12-08 14:32:49 +01:00
< td style = " width:20px; cursor:pointer " class = " hide-border td-icon " >
2013-12-13 10:13:57 +01:00
& nbsp ; < i data - bind = " click: $parent .removeItem, visible: actionsVisible() && $parent .invoice_items().length > 1 " class = " fa fa-minus-circle " title = " Remove item " />
2013-11-26 22:45:10 +01:00
</ td >
</ tr >
</ tbody >
< tfoot >
2013-12-01 21:58:25 +01:00
< tr >
2013-12-29 00:33:48 +01:00
< td class = " hide-border " />
< td data - bind = " attr: { colspan: tax_rates().length > 1 ? 3 : 2} " />
2013-11-26 22:45:10 +01:00
< td colspan = " 2 " > Subtotal </ td >
< td style = " text-align: right " >< span data - bind = " text: subtotal " /></ td >
</ tr >
< tr data - bind = " visible: discount() > 0 " >
2013-12-27 10:10:32 +01:00
< td class = " hide-border " data - bind = " attr: { colspan: tax_rates().length > 1 ? 4 : 3} " />
2013-11-26 22:45:10 +01:00
< td colspan = " 2 " > Discount </ td >
< td style = " text-align: right " >< span data - bind = " text: discounted " /></ td >
</ tr >
2013-12-30 21:17:45 +01:00
< tr >
< td class = " hide-border " data - bind = " attr: { colspan: tax_rates().length > 1 ? 4 : 3} " />
< td colspan = " 2 " > Paid to Date </ td >
< td style = " text-align: right " ></ td >
</ tr >
2013-11-26 22:45:10 +01:00
< tr >
2013-12-27 10:10:32 +01:00
< td class = " hide-border " data - bind = " attr: { colspan: tax_rates().length > 1 ? 4 : 3} " />
2013-12-11 21:33:44 +01:00
< td colspan = " 2 " >< b > Balance Due </ b ></ td >
2013-11-26 22:45:10 +01:00
< td style = " text-align: right " >< span data - bind = " text: total " /></ td >
</ tr >
</ tfoot >
</ table >
2013-11-26 13:45:07 +01:00
2013-11-26 22:45:10 +01:00
< p >& nbsp ; </ p >
< div class = " form-actions " >
2013-12-03 18:32:33 +01:00
2013-12-07 19:45:00 +01:00
< div style = " display:none " >
{{ Former :: text ( 'action' ) }}
@ if ( $invoice )
2013-12-05 21:25:20 +01:00
{{ Former :: text ( 'id' ) }}
2013-12-07 19:45:00 +01:00
@ endif
</ div >
2013-12-11 21:33:44 +01:00
{{ Button :: normal ( 'Download PDF' , array ( 'onclick' => 'onDownloadClick()' )) }}
2013-12-07 19:45:00 +01:00
@ if ( $invoice )
2013-12-11 21:33:44 +01:00
{{ DropdownButton :: primary ( 'Save Invoice' ,
2013-12-03 18:32:33 +01:00
Navigation :: links (
array (
2013-12-11 21:33:44 +01:00
array ( 'Save Invoice' , " javascript:onSaveClick() " ),
array ( 'Clone Invoice' , " javascript:onCloneClick() " ),
2013-12-03 18:32:33 +01:00
array ( Navigation :: DIVIDER ),
array ( 'Archive Invoice' , " javascript:onArchiveClick() " ),
array ( 'Delete Invoice' , " javascript:onDeleteClick() " ),
)
)
, array ( 'id' => 'actionDropDown' , 'style' => 'text-align:left' )) -> split (); }}
@ else
2013-12-11 21:33:44 +01:00
{{ Button :: primary_submit ( 'Save Invoice' ) }}
2013-12-03 18:32:33 +01:00
@ endif
2013-12-10 23:10:43 +01:00
{{ Button :: primary ( 'Send Email' , array ( 'id' => 'email_button' , 'onclick' => 'onEmailClick()' )) }}
2013-11-26 13:45:07 +01:00
</ div >
2013-11-26 22:45:10 +01:00
< p >& nbsp ; </ p >
<!-- < textarea rows = " 20 " cols = " 120 " id = " pdfText " onkeyup = " runCode() " ></ textarea > -->
2013-11-27 08:38:37 +01:00
<!-- < iframe frameborder = " 1 " width = " 100% " height = " 600 " style = " display:block;margin: 0 auto " ></ iframe > -->
2013-12-11 21:33:44 +01:00
< iframe id = " theIFrame " frameborder = " 1 " width = " 100% " height = " 500 " ></ iframe >
< canvas id = " theCanvas " style = " display:none;width:100%;border:solid 1px #CCCCCC; " ></ canvas >
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 " >
2013-12-05 21:25:20 +01:00
< div class = " modal-dialog " style = " min-width:1000px " >
2013-11-26 13:45:07 +01:00
< div class = " modal-content " >
< div class = " modal-header " >
< button type = " button " class = " close " data - dismiss = " modal " aria - hidden = " true " >& times ; </ button >
2013-12-27 10:10:32 +01:00
< h4 class = " modal-title " id = " clientModalLabel " > New Client </ h4 >
2013-11-26 13:45:07 +01:00
</ div >
2013-12-05 21:25:20 +01:00
2013-12-27 10:10:32 +01:00
< div class = " container " style = " width: 100% " >
< div style = " background-color: #F6F6F6 " class = " row " data - bind = " with: client " onkeypress = " clientModalEnterClick(event) " >
< div class = " col-md-6 " style = " margin-left:0px;margin-right:0px " >
2013-12-05 21:25:20 +01:00
2013-12-13 10:13:57 +01:00
{{ Former :: legend ( 'Contacts' ) }}
< div data - bind = ' template : { foreach : contacts ,
beforeRemove : hideContact ,
afterAdd : showContact } ' >
{{ Former :: hidden ( 'public_id' ) -> data_bind ( " value: public_id, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'first_name' ) -> data_bind ( " value: first_name, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'last_name' ) -> data_bind ( " value: last_name, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'email' ) -> data_bind ( " value: email, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'phone' ) -> data_bind ( " value: phone, valueUpdate: 'afterkeydown' " ) }}
< div class = " form-group " >
< div class = " col-lg-8 col-lg-offset-4 " >
< span data - bind = " visible: $parent .contacts().length > 1 " >
{{ link_to ( '#' , 'Remove contact' , array ( 'data-bind' => 'click: $parent.removeContact' )) }}
</ span >
< span data - bind = " visible: $index () === ( $parent .contacts().length - 1) " class = " pull-right " >
{{ link_to ( '#' , 'Add contact' , array ( 'data-bind' => 'click: $parent.addContact' )) }}
</ span >
</ div >
</ div >
</ div >
{{ Former :: legend ( 'Additional Info' ) }}
2013-12-29 18:40:11 +01:00
{{ Former :: select ( 'currency_id' ) -> addOption ( '' , '' ) -> label ( 'Currency' ) -> data_bind ( 'value: currency_id' )
-> fromQuery ( $currencies , 'name' , 'id' ) }}
2013-12-24 22:27:36 +01:00
{{ Former :: select ( 'client_size_id' ) -> addOption ( '' , '' ) -> label ( 'Size' ) -> data_bind ( 'value: client_size_id' )
2013-12-13 10:13:57 +01:00
-> fromQuery ( $clientSizes , 'name' , 'id' ) -> select ( $client ? $client -> client_size_id : '' ) }}
2013-12-24 22:27:36 +01:00
{{ Former :: select ( 'client_industry_id' ) -> addOption ( '' , '' ) -> label ( 'Industry' ) -> data_bind ( 'value: client_industry_id' )
2013-12-13 10:13:57 +01:00
-> fromQuery ( $clientIndustries , 'name' , 'id' ) -> select ( $client ? $client -> client_industry_id : '' ) }}
2013-12-30 21:17:45 +01:00
{{ Former :: textarea ( 'private_notes' ) -> data_bind ( 'value: private_notes' ) }}
2013-12-13 10:13:57 +01:00
2013-12-30 21:17:45 +01:00
</ div >
< div class = " col-md-6 " style = " margin-left:0px;margin-right:0px " >
{{ Former :: legend ( 'Organization' ) }}
{{ Former :: text ( 'name' ) -> data_bind ( " value: name, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'website' ) -> data_bind ( " value: website, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'work_phone' ) -> data_bind ( " value: work_phone, valueUpdate: 'afterkeydown' " ) -> label ( 'Phone' ) }}
{{ Former :: legend ( 'Address' ) }}
{{ Former :: text ( 'address1' ) -> label ( 'Street' ) -> data_bind ( " value: address1, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'address2' ) -> label ( 'Apt/Floor' ) -> data_bind ( " value: address2, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'city' ) -> data_bind ( " value: city, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'state' ) -> data_bind ( " value: state, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: text ( 'postal_code' ) -> data_bind ( " value: postal_code, valueUpdate: 'afterkeydown' " ) }}
{{ Former :: select ( 'country_id' ) -> addOption ( '' , '' ) -> label ( 'Country' ) -> addGroupClass ( 'country_select' )
-> fromQuery ( $countries , 'name' , 'id' ) -> data_bind ( " dropdown: country_id " ) }}
2013-12-05 21:25:20 +01:00
</ div >
</ div >
2013-12-27 10:10:32 +01:00
</ div >
2013-12-05 21:25:20 +01:00
2013-12-27 10:10:32 +01:00
< div class = " modal-footer " style = " margin-top: 0px " >
2013-12-30 21:17:45 +01:00
< span class = " error-block " id = " emailError " style = " display:none;float:left " > Please provide a valid email address .</ span >< span >& nbsp ; </ span >
2013-12-05 21:25:20 +01:00
< button type = " button " class = " btn btn-default " data - dismiss = " modal " > Cancel </ button >
2013-12-13 10:13:57 +01:00
< button type = " button " class = " btn btn-primary " data - bind = " click: clientFormComplete " > Done </ button >
2013-12-27 10:10:32 +01:00
</ div >
</ div >
</ div >
</ div >
< div class = " modal fade " id = " taxModal " tabindex = " -1 " role = " dialog " aria - labelledby = " taxModalLabel " 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 = " taxModalLabel " > Tax Rates </ h4 >
2013-11-26 13:45:07 +01:00
</ div >
2013-12-27 10:10:32 +01:00
< div style = " background-color: #F6F6F6 " onkeypress = " taxModalEnterClick(event) " >
< table class = " table invoice-table sides-padded " style = " margin-bottom: 0px !important " >
< thead >
< tr >
< th class = " hide-border " ></ th >
< th class = " hide-border " > Name </ th >
< th class = " hide-border " > Rate </ th >
< th class = " hide-border " ></ th >
</ tr >
</ thead >
< tbody data - bind = " foreach: tax_rates " >
< tr data - bind = " event: { mouseover: showActions, mouseout: hideActions } " >
< td style = " width:10px " class = " hide-border " ></ td >
< td style = " width:60px " >
< input onkeyup = " onTaxRateChange() " data - bind = " value: name, valueUpdate: 'afterkeydown' " class = " form-control " onchange = " refreshPDF() " //>
</ td >
< td style = " width:60px " >
2013-12-29 12:28:44 +01:00
< input onkeyup = " onTaxRateChange() " data - bind = " value: prettyRate, valueUpdate: 'afterkeydown' " style = " text-align: right " class = " form-control " onchange = " refreshPDF() " //>
2013-12-27 10:10:32 +01:00
</ td >
< td style = " width:10px; cursor:pointer " class = " hide-border td-icon " >
& nbsp ; < i data - bind = " click: $parent .removeTaxRate, visible: actionsVisible() && $parent .tax_rates().length > 1 " class = " fa fa-minus-circle " title = " Remove item " />
</ td >
</ tr >
</ tbody >
</ table >
& nbsp ;
</ div >
< div class = " modal-footer " style = " margin-top: 0px " >
2013-12-29 12:28:44 +01:00
<!-- < button type = " button " class = " btn btn-default " data - dismiss = " modal " > Cancel </ button > -->
2013-12-27 10:10:32 +01:00
< button type = " button " class = " btn btn-primary " data - bind = " click: taxFormComplete " > Done </ button >
</ div >
2013-12-05 21:25:20 +01:00
2013-11-26 13:45:07 +01:00
</ div >
</ div >
</ div >
2013-12-27 10:10:32 +01:00
2013-11-26 13:45:07 +01:00
{{ Former :: close () }}
< script type = " text/javascript " >
2013-11-27 08:38:37 +01:00
2013-11-26 13:45:07 +01:00
$ ( function () {
2013-12-30 21:17:45 +01:00
//$('form').change(refreshPDF);
2013-12-11 21:33:44 +01:00
2013-12-05 21:25:20 +01:00
$ ( '#country_id' ) . combobox ();
2013-12-24 22:27:36 +01:00
$ ( '[rel=tooltip]' ) . tooltip ();
2013-12-05 21:25:20 +01:00
2013-11-28 13:15:34 +01:00
$ ( '#invoice_date' ) . datepicker ({
2013-11-26 13:45:07 +01:00
autoclose : true ,
todayHighlight : true
});
2013-12-10 18:18:35 +01:00
$ ( '#due_date, #start_date, #end_date' ) . datepicker ({
2013-11-28 17:40:13 +01:00
autoclose : true ,
todayHighlight : true
});
2013-12-29 18:40:11 +01:00
@ if ( $client && ! $invoice )
$ ( 'input[name=client]' ) . val ({{ $client -> public_id }});
@ endif
2013-11-26 13:45:07 +01:00
var $input = $ ( 'select#client' );
$input . combobox ();
2013-12-08 14:32:49 +01:00
$ ( '.client_select input.form-control' ) . on ( 'change' , function ( e ) {
2013-12-11 21:33:44 +01:00
var clientId = parseInt ( $ ( 'input[name=client]' ) . val (), 10 );
2013-12-17 14:14:47 +01:00
if ( clientId > 0 ) {
model . loadClient ( clientMap [ clientId ]);
2013-12-13 10:13:57 +01:00
} else {
2013-12-17 14:14:47 +01:00
model . client . public_id ( 0 ); // TODO_FIX
2013-12-08 14:32:49 +01:00
}
2013-12-30 21:17:45 +01:00
refreshPDF ();
2013-12-13 10:13:57 +01:00
}) . trigger ( 'change' );
2013-11-26 13:45:07 +01:00
2013-12-30 21:17:45 +01:00
$ ( '#terms, #public_notes, #invoice_number, #invoice_date, #due_date, #po_number, #discout, #currency_id' ) . change ( function () {
refreshPDF ();
});
2013-12-24 22:27:36 +01:00
$ ( '.country_select input.form-control' ) . on ( 'change' , function ( e ) {
var countryId = parseInt ( $ ( 'input[name=country_id]' ) . val (), 10 );
model . client . country_id ( countryId );
});
2013-11-26 13:45:07 +01:00
@ if ( $client )
2013-12-08 20:08:17 +01:00
$ ( '#invoice_number' ) . focus ();
2013-11-26 13:45:07 +01:00
@ else
2013-12-07 19:45:00 +01:00
//$('[name="client_combobox"]').focus();
2013-11-26 13:45:07 +01:00
@ endif
2013-12-29 00:33:48 +01:00
$ ( '#clientModal' ) . on ( 'shown.bs.modal' , function () {
2013-12-30 21:17:45 +01:00
$ ( '#first_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 );
refreshPDF ();
}
2013-11-26 13:45:07 +01:00
})
2013-12-17 14:14:47 +01:00
2013-12-27 10:10:32 +01:00
$ ( '#taxModal' ) . on ( 'shown.bs.modal' , function () {
$ ( '#taxModal input:first' ) . focus ();
2013-12-29 00:33:48 +01:00
}) . on ( 'hidden.bs.modal' , function () {
if ( model . taxBackup ) {
}
})
2013-12-27 10:10:32 +01:00
2013-12-03 18:32:33 +01:00
$ ( '#actionDropDown > button:first' ) . click ( function () {
2013-12-11 21:33:44 +01:00
onSaveClick ();
2013-12-03 18:32:33 +01:00
});
2013-12-10 23:10:43 +01:00
$ ( 'label.radio' ) . addClass ( 'radio-inline' );
2013-11-27 08:38:37 +01:00
applyComboboxListeners ();
refreshPDF ();
2013-12-17 14:14:47 +01:00
});
2013-11-26 13:45:07 +01:00
2013-11-27 08:38:37 +01:00
function applyComboboxListeners () {
var value ;
$ ( '.datalist' ) . on ( 'focus' , function () {
value = $ ( this ) . val ();
}) . on ( 'blur' , function () {
if ( value != $ ( this ) . val ()) refreshPDF ();
2013-12-03 18:32:33 +01:00
}) . on ( 'input' , function () {
2013-11-27 08:38:37 +01:00
var key = $ ( this ) . val ();
for ( var i = 0 ; i < products . length ; i ++ ) {
var product = products [ i ];
2013-12-04 17:20:14 +01:00
if ( product . product_key == key ) {
2013-11-27 08:38:37 +01:00
var model = ko . dataFor ( this );
2013-12-29 12:28:44 +01:00
//model.notes(product.notes);
//model.cost(product.cost);
//model.qty(product.qty);
2013-11-27 08:38:37 +01:00
break ;
}
}
});
}
2013-11-26 13:45:07 +01:00
function createInvoiceModel () {
2013-12-13 10:13:57 +01:00
var invoice = ko . toJS ( model );
@ if ( file_exists ( $account -> getLogoPath ()))
invoice . image = " { { HTML::image_data( $account->getLogoPath ()) }} " ;
invoice . imageWidth = {{ $account -> getLogoWidth () }};
invoice . imageHeight = {{ $account -> getLogoHeight () }};
@ endif
2013-11-26 13:45:07 +01:00
return invoice ;
}
function refreshPDF () {
2013-12-07 19:45:00 +01:00
setTimeout ( function () {
_refreshPDF ();
}, 100 );
}
2013-12-08 14:32:49 +01:00
2013-12-07 19:45:00 +01:00
function _refreshPDF () {
2013-12-13 10:13:57 +01:00
console . log ( " refreshPDF " );
2013-11-26 13:45:07 +01:00
var invoice = createInvoiceModel ();
2013-12-11 21:33:44 +01:00
var doc = generatePDF ( invoice );
/*
2013-12-08 14:32:49 +01:00
var string = doc . output ( 'dataurlstring' );
var pdfAsArray = convertDataURIToBinary ( string );
PDFJS . getDocument ( pdfAsArray ) . then ( function getPdfHelloWorld ( pdf ) {
pdf . getPage ( 1 ) . then ( function getPageHelloWorld ( page ) {
var scale = 1.5 ;
var viewport = page . getViewport ( scale );
2013-12-11 21:33:44 +01:00
var canvas = document . getElementById ( 'theCanvas' );
2013-12-08 14:32:49 +01:00
var context = canvas . getContext ( '2d' );
canvas . height = viewport . height ;
canvas . width = viewport . width ;
page . render ({ canvasContext : context , viewport : viewport });
});
2013-12-08 20:08:17 +01:00
});
2013-12-11 21:33:44 +01:00
*/
2013-12-08 14:32:49 +01:00
2013-12-11 21:33:44 +01:00
var string = doc . output ( 'datauristring' );
$ ( '#theIFrame' ) . attr ( 'src' , string );
2013-12-07 19:45:00 +01:00
}
2013-11-26 13:45:07 +01:00
function onDownloadClick () {
var invoice = createInvoiceModel ();
var doc = generatePDF ( invoice );
2013-12-08 20:08:17 +01:00
doc . save ( 'Invoice-' + $ ( '#invoice_number' ) . val () + '.pdf' );
2013-11-26 13:45:07 +01:00
}
function onEmailClick () {
if ( confirm ( 'Are you sure you want to email this invoice?' )) {
2013-12-03 18:32:33 +01:00
$ ( '#action' ) . val ( 'email' );
2013-11-26 13:45:07 +01:00
$ ( '.main_form' ) . submit ();
}
}
2013-12-11 21:33:44 +01:00
function onSaveClick () {
$ ( '.main_form' ) . submit ();
}
function onCloneClick () {
$ ( '#action' ) . val ( 'clone' );
$ ( '.main_form' ) . submit ();
}
2013-12-03 18:32:33 +01:00
function onArchiveClick () {
$ ( '#action' ) . val ( 'archive' );
$ ( '.main_form' ) . submit ();
}
function onDeleteClick () {
if ( confirm ( 'Are you sure you want to delete this invoice?' )) {
$ ( '#action' ) . val ( 'delete' );
$ ( '.main_form' ) . submit ();
}
}
2013-12-13 10:13:57 +01:00
function formEnterClick ( event ) {
if ( event . keyCode === 13 ){
if ( event . target . type == 'textarea' ) {
return ;
2013-12-11 21:33:44 +01:00
}
2013-11-26 13:45:07 +01:00
2013-12-13 10:13:57 +01:00
event . preventDefault ();
$ ( '.main_form' ) . submit ();
return false ;
2013-11-26 13:45:07 +01:00
}
2013-12-13 10:13:57 +01:00
}
2013-12-05 21:25:20 +01:00
2013-12-27 10:10:32 +01:00
function clientModalEnterClick ( event ) {
2013-11-26 13:45:07 +01:00
if ( event . keyCode === 13 ){
event . preventDefault ();
2013-12-13 10:13:57 +01:00
model . clientFormComplete ();
2013-11-26 13:45:07 +01:00
return false ;
}
}
2013-12-27 10:10:32 +01:00
function taxModalEnterClick ( event ) {
if ( event . keyCode === 13 ){
event . preventDefault ();
model . taxFormComplete ();
return false ;
}
}
2013-11-26 13:45:07 +01:00
function InvoiceModel () {
2013-12-13 10:13:57 +01:00
var self = this ;
this . client = new ClientModel ();
self . discount = ko . observable ( '' );
self . frequency_id = ko . observable ( '' );
2013-12-29 18:40:11 +01:00
self . currency_id = ko . observable ({{ Session :: get ( SESSION_CURRENCY , DEFAULT_CURRENCY ) }});
2013-12-15 13:55:50 +01:00
self . terms = ko . observable ( '' );
2013-12-30 21:17:45 +01:00
self . public_notes = ko . observable ( '' );
2013-12-13 10:13:57 +01:00
self . po_number = ko . observable ( '' );
self . invoice_date = ko . observable ( '' );
2013-12-15 13:55:50 +01:00
self . invoice_number = ko . observable ( '' );
2013-12-13 10:13:57 +01:00
self . due_date = ko . observable ( '' );
self . start_date = ko . observable ( '' );
self . end_date = ko . observable ( '' );
self . is_recurring = ko . observable ( false );
self . invoice_status_id = ko . observable ( 0 );
2013-12-27 10:10:32 +01:00
2013-12-13 10:13:57 +01:00
self . invoice_items = ko . observableArray ();
2013-12-27 10:10:32 +01:00
self . tax_rates = ko . observableArray ();
2013-12-13 10:13:57 +01:00
self . mapping = {
'invoice_items' : {
create : function ( options ) {
return new ItemModel ( options . data );
}
}
}
2013-12-17 14:14:47 +01:00
self . loadClient = function ( client ) {
//console.log(client);
ko . mapping . fromJS ( client , model . client . mapping , model . client );
}
2013-12-15 13:55:50 +01:00
self . wrapped_terms = ko . computed ({
read : function () {
2013-12-30 21:17:45 +01:00
$ ( '#terms' ) . height ( this . terms () . split ( '\n' ) . length * 36 );
2013-12-15 13:55:50 +01:00
return this . terms ();
},
write : function ( value ) {
2013-12-30 21:17:45 +01:00
value = wordWrapText ( value , 340 );
2013-12-15 13:55:50 +01:00
self . terms ( value );
2013-12-30 21:17:45 +01:00
$ ( '#terms' ) . height ( value . split ( '\n' ) . length * 36 );
},
owner : this
});
self . wrapped_notes = ko . computed ({
read : function () {
$ ( '#public_notes' ) . height ( this . public_notes () . split ( '\n' ) . length * 36 );
return this . public_notes ();
},
write : function ( value ) {
value = wordWrapText ( value , 340 );
self . public_notes ( value );
$ ( '#public_notes' ) . height ( value . split ( '\n' ) . length * 36 );
2013-12-15 13:55:50 +01:00
},
owner : this
});
2013-12-13 10:13:57 +01:00
self . showClientText = ko . computed ( function () {
return self . client . public_id () ? 'Edit client details' : 'Create new client' ;
});
2013-12-27 10:10:32 +01:00
self . showTaxesForm = function () {
2013-12-29 00:33:48 +01:00
self . taxBackup = ko . mapping . toJS ( self . tax_rates );
2013-12-27 10:10:32 +01:00
$ ( '#taxModal' ) . modal ( 'show' );
}
self . taxFormComplete = function () {
2013-12-29 00:33:48 +01:00
model . taxBackup = false ;
2013-12-27 10:10:32 +01:00
$ ( '#taxModal' ) . modal ( 'hide' );
}
2013-12-13 10:13:57 +01:00
self . showClientForm = function () {
2013-12-17 14:14:47 +01:00
self . clientBackup = ko . mapping . toJS ( self . client );
2013-12-27 10:10:32 +01:00
//console.log(self.clientBackup);
2013-12-17 14:14:47 +01:00
2013-12-13 10:13:57 +01:00
if ( self . client . public_id () == 0 ) {
2013-12-27 10:10:32 +01:00
$ ( '#clientModal input' ) . val ( '' );
$ ( '#clientModal #country_id' ) . val ( '' );
2013-12-13 10:13:57 +01:00
}
2013-12-30 21:17:45 +01:00
$ ( '#emailError' ) . css ( " display " , " none " );
2013-12-27 10:10:32 +01:00
$ ( '#clientModal' ) . modal ( 'show' );
2013-12-13 10:13:57 +01:00
}
self . clientFormComplete = function () {
2013-12-30 21:17:45 +01:00
var email = $ ( '#email' ) . val ();
var firstName = $ ( '#first_name' ) . val ();
var lastName = $ ( '#last_name' ) . val ();
2013-12-13 10:13:57 +01:00
var name = $ ( '#name' ) . val ();
2013-12-30 21:17:45 +01:00
if ( ! email || ! isValidEmailAddress ( email )) {
$ ( '#emailError' ) . css ( " display " , " inline " );
2013-12-13 10:13:57 +01:00
return ;
}
$ ( 'select#client' ) . combobox ( 'setSelected' );
if ( self . client . public_id () == 0 ) {
self . client . public_id ( - 1 );
}
2013-12-30 21:17:45 +01:00
if ( name ) {
//
} else if ( firstName || lastName ) {
name = firstName + ' ' + lastName ;
} else {
name = email ;
}
2013-12-13 10:13:57 +01:00
$ ( '.client_select input.form-control' ) . val ( name );
$ ( '.client_select .combobox-container' ) . addClass ( 'combobox-selected' );
2013-12-30 21:17:45 +01:00
$ ( '#emailError' ) . css ( " display " , " none " );
2013-12-13 10:13:57 +01:00
$ ( '.client_select input.form-control' ) . focus ();
refreshPDF ();
2013-12-17 14:14:47 +01:00
model . clientBackup = false ;
2013-12-27 10:10:32 +01:00
$ ( '#clientModal' ) . modal ( 'hide' );
2013-12-13 10:13:57 +01:00
}
2013-12-03 18:32:33 +01:00
2013-11-26 13:45:07 +01:00
self . removeItem = function ( item ) {
2013-12-13 10:13:57 +01:00
self . invoice_items . remove ( item );
2013-11-26 13:45:07 +01:00
refreshPDF ();
}
self . addItem = function () {
2013-12-29 00:33:48 +01:00
var itemModel = new ItemModel ();
self . invoice_items . push ( itemModel );
2013-12-29 12:28:44 +01:00
applyComboboxListeners ();
2013-11-26 13:45:07 +01:00
}
2013-12-27 10:10:32 +01:00
self . removeTaxRate = function ( taxRate ) {
self . tax_rates . remove ( taxRate );
//refreshPDF();
}
2013-12-29 00:33:48 +01:00
self . addTaxRate = function ( data ) {
2013-12-29 12:28:44 +01:00
var itemModel = new TaxRateModel ( data );
self . tax_rates . push ( itemModel );
2013-12-27 10:10:32 +01:00
applyComboboxListeners ();
}
2013-11-26 13:45:07 +01:00
this . rawSubtotal = ko . computed ( function () {
var total = 0 ;
2013-12-13 10:13:57 +01:00
for ( var p = 0 ; p < self . invoice_items () . length ; ++ p )
2013-11-26 13:45:07 +01:00
{
2013-12-13 10:13:57 +01:00
total += self . invoice_items ()[ p ] . rawTotal ();
2013-11-26 13:45:07 +01:00
}
return total ;
});
this . subtotal = ko . computed ( function () {
var total = self . rawSubtotal ();
2013-12-29 18:40:11 +01:00
return total > 0 ? formatMoney ( total , self . currency_id ()) : '' ;
2013-11-26 13:45:07 +01:00
});
this . discounted = ko . computed ( function () {
var total = self . rawSubtotal () * ( self . discount () / 100 );
2013-12-29 18:40:11 +01:00
return formatMoney ( total , self . currency_id ());
2013-11-26 13:45:07 +01:00
});
this . total = ko . computed ( function () {
var total = self . rawSubtotal ();
2013-12-11 21:33:44 +01:00
var discount = parseFloat ( self . discount ());
2013-11-26 13:45:07 +01:00
if ( discount > 0 ) {
total = total * (( 100 - discount ) / 100 );
}
2013-12-29 18:40:11 +01:00
return total > 0 ? formatMoney ( total , self . currency_id ()) : '' ;
2013-11-26 13:45:07 +01:00
});
self . onDragged = function ( item ) {
refreshPDF ();
}
}
2013-12-13 10:13:57 +01:00
function ClientModel ( data ) {
var self = this ;
self . public_id = ko . observable ( 0 );
self . name = ko . observable ( '' );
self . work_phone = ko . observable ( '' );
2013-12-30 21:17:45 +01:00
self . private_notes = ko . observable ( '' );
2013-12-13 10:13:57 +01:00
self . address1 = ko . observable ( '' );
self . address2 = ko . observable ( '' );
self . city = ko . observable ( '' );
self . state = ko . observable ( '' );
self . postal_code = ko . observable ( '' );
self . country_id = ko . observable ( '' );
self . client_size_id = ko . observable ( '' );
self . client_industry_id = ko . observable ( '' );
2013-12-29 18:40:11 +01:00
self . currency_id = ko . observable ( '' );
2013-12-15 13:55:50 +01:00
self . website = ko . observable ( '' );
2013-12-13 10:13:57 +01:00
self . contacts = ko . observableArray ();
self . mapping = {
'contacts' : {
create : function ( options ) {
return new ContactModel ( options . data );
}
}
}
self . showContact = function ( elem ) { if ( elem . nodeType === 1 ) $ ( elem ) . hide () . slideDown () }
self . hideContact = function ( elem ) { if ( elem . nodeType === 1 ) $ ( elem ) . slideUp ( function () { $ ( elem ) . remove (); }) }
self . addContact = function () {
var contact = new ContactModel ();
console . log ( 'num: ' + self . contacts () . length );
if ( self . contacts () . length == 0 ) {
contact . send_invoice ( true );
}
self . contacts . push ( contact );
return false ;
}
self . removeContact = function () {
self . contacts . remove ( this );
}
2013-12-30 21:17:45 +01:00
self . placeholderName = ko . computed ( function () {
if ( self . contacts () . length == 0 ) return ;
var contact = self . contacts ()[ 0 ];
if ( contact . first_name () || contact . last_name ()) {
return contact . first_name () + ' ' + contact . last_name ();
} else {
return '' ;
}
});
2013-12-13 10:13:57 +01:00
if ( data ) {
ko . mapping . fromJS ( data , {}, this );
} else {
self . addContact ();
}
}
function ContactModel ( data ) {
2013-11-26 13:45:07 +01:00
var self = this ;
2013-12-13 10:13:57 +01:00
self . public_id = ko . observable ( '' );
self . first_name = ko . observable ( '' );
self . last_name = ko . observable ( '' );
self . email = ko . observable ( '' );
self . phone = ko . observable ( '' );
self . send_invoice = ko . observable ( false );
if ( data ) {
ko . mapping . fromJS ( data , {}, this );
}
self . fullName = ko . computed ( function () {
return self . first_name () + ' ' + self . last_name ();
});
}
2013-12-27 10:10:32 +01:00
function TaxRateModel ( data ) {
var self = this ;
2013-12-29 00:33:48 +01:00
self . public_id = ko . observable ( '' );
self . rate = ko . observable ();
self . name = ko . observable ( '' );
2013-12-29 12:28:44 +01:00
self . is_deleted = ko . observable ( false );
2013-12-29 00:33:48 +01:00
self . actionsVisible = ko . observable ( false );
2013-12-27 10:10:32 +01:00
2013-12-29 00:33:48 +01:00
if ( data ) {
ko . mapping . fromJS ( data , {}, this );
}
2013-12-29 12:28:44 +01:00
this . prettyRate = ko . computed ({
read : function () {
return this . rate () ? parseFloat ( this . rate ()) : '' ;
},
write : function ( value ) {
this . rate ( value );
},
owner : this
});
2013-12-29 00:33:48 +01:00
self . displayName = ko . computed ( function () {
var name = self . name () ? self . name () : false ;
2013-12-29 12:28:44 +01:00
var rate = self . rate () ? parseFloat ( self . rate ()) : false ;
2013-12-29 00:33:48 +01:00
return ( name && rate ) ? ( rate + '%' + ' - ' + name ) : '' ;
});
self . hideActions = function () {
self . actionsVisible ( false );
2013-12-27 10:10:32 +01:00
}
2013-12-29 00:33:48 +01:00
self . showActions = function () {
self . actionsVisible ( true );
2013-12-27 10:10:32 +01:00
}
2013-12-29 00:33:48 +01:00
self . isEmpty = function () {
2013-12-27 10:10:32 +01:00
return ! self . rate () && ! self . name ();
}
}
2013-12-13 10:13:57 +01:00
function ItemModel ( data ) {
var self = this ;
2013-11-26 13:45:07 +01:00
this . product_key = ko . observable ( '' );
this . notes = ko . observable ( '' );
this . cost = ko . observable ();
this . qty = ko . observable ();
2013-12-29 00:33:48 +01:00
this . tax = ko . observable ();
2013-11-26 13:45:07 +01:00
this . actionsVisible = ko . observable ( false );
2013-12-29 18:40:11 +01:00
2013-12-29 12:28:44 +01:00
this . prettyQty = ko . computed ({
read : function () {
return this . qty () ? parseFloat ( this . qty ()) : '' ;
},
write : function ( value ) {
this . qty ( value );
},
owner : this
});
2013-12-13 10:13:57 +01:00
if ( data ) {
2013-12-29 12:28:44 +01:00
ko . mapping . fromJS ( data , {}, this );
2013-12-29 18:40:11 +01:00
if ( this . cost ()) this . cost ( formatMoney ( this . cost (), model . currency_id (), true ));
2013-12-29 00:33:48 +01:00
}
for ( var i = 0 ; i < model . tax_rates () . length ; i ++ ) {
var taxRate = model . tax_rates ()[ i ];
2013-12-29 12:28:44 +01:00
if ( data && ( data . tax_name == taxRate . name () && data . tax_rate == taxRate . rate ())) {
2013-12-29 00:33:48 +01:00
self . tax ( taxRate );
2013-12-29 12:28:44 +01:00
break ;
} else if (( ! data || ! data . tax_name ) && ! taxRate . name ()) {
2013-12-29 00:33:48 +01:00
self . tax ( taxRate );
2013-12-29 12:28:44 +01:00
break ;
2013-12-29 00:33:48 +01:00
}
}
2013-12-29 12:28:44 +01:00
// if the tax was deleted but exists for the line item
if ( data && data . tax_name && ( parseFloat ( data . tax_rate )) && ! self . tax ()) {
var taxRate = new TaxRateModel ();
taxRate . rate ( parseFloat ( data . tax_rate ));
taxRate . name ( data . tax_name );
taxRate . is_deleted ( true );
model . tax_rates . push ( taxRate );
self . tax ( taxRate );
}
2013-12-13 10:13:57 +01:00
2013-12-15 13:55:50 +01:00
self . wrapped_notes = ko . computed ({
read : function () {
return this . notes ();
},
write : function ( value ) {
value = wordWrapText ( value );
self . notes ( value );
2013-12-27 10:10:32 +01:00
onItemChange ();
2013-12-15 13:55:50 +01:00
},
owner : this
});
2013-11-26 13:45:07 +01:00
this . rawTotal = ko . computed ( function () {
var cost = parseFloat ( self . cost ());
2013-12-08 14:32:49 +01:00
var qty = parseFloat ( self . qty ());
2013-12-29 00:33:48 +01:00
var taxRate = self . tax () ? parseFloat ( self . tax () . rate ()) : 0 ;
var value = cost * qty ;
if ( taxRate > 0 ) {
value += value * ( taxRate / 100 );
}
2013-11-26 13:45:07 +01:00
return value ? value : '' ;
2013-12-29 00:33:48 +01:00
});
2013-11-26 13:45:07 +01:00
this . total = ko . computed ( function () {
var total = self . rawTotal ();
2013-12-29 18:40:11 +01:00
return total ? formatMoney ( total , model . currency_id ()) : '' ;
2013-11-26 13:45:07 +01:00
});
this . hideActions = function () {
this . actionsVisible ( false );
}
this . showActions = function () {
this . actionsVisible ( true );
}
2013-12-01 13:22:08 +01:00
this . isEmpty = function () {
2013-12-29 00:33:48 +01:00
return ! self . product_key () && ! self . notes () && ! self . cost () && ! self . qty ();
2013-12-01 13:22:08 +01:00
}
2013-12-29 00:33:48 +01:00
this . onSelect = function (){
console . log ( " select " );
}
2013-12-01 13:22:08 +01:00
}
2013-12-27 10:10:32 +01:00
function onItemChange ()
2013-12-01 13:22:08 +01:00
{
var hasEmpty = false ;
2013-12-13 10:13:57 +01:00
for ( var i = 0 ; i < model . invoice_items () . length ; i ++ ) {
var item = model . invoice_items ()[ i ];
2013-12-01 13:22:08 +01:00
if ( item . isEmpty ()) {
hasEmpty = true ;
}
}
2013-12-27 10:10:32 +01:00
2013-12-01 13:22:08 +01:00
if ( ! hasEmpty ) {
model . addItem ();
}
2013-12-15 13:55:50 +01:00
$ ( '.word-wrap' ) . each ( function ( index , input ) {
$ ( input ) . height ( $ ( input ) . val () . split ( '\n' ) . length * 22 );
});
2013-11-26 13:45:07 +01:00
}
2013-12-27 10:10:32 +01:00
function onTaxRateChange ()
{
var hasEmpty = false ;
for ( var i = 0 ; i < model . tax_rates () . length ; i ++ ) {
var taxRate = model . tax_rates ()[ i ];
if ( taxRate . isEmpty ()) {
hasEmpty = true ;
}
}
if ( ! hasEmpty ) {
model . addTaxRate ();
}
}
2013-11-27 08:38:37 +01:00
var products = {{ $products }};
2013-12-07 19:45:00 +01:00
var clients = {{ $clients }};
var clientMap = {};
2013-12-30 21:17:45 +01:00
var $clientSelect = $ ( 'select#client' );
2013-12-07 19:45:00 +01:00
for ( var i = 0 ; i < clients . length ; i ++ ) {
var client = clients [ i ];
2013-12-15 13:55:50 +01:00
for ( var j = 0 ; j < client . contacts . length ; j ++ ) {
var contact = client . contacts [ j ];
2013-12-13 10:13:57 +01:00
contact . send_invoice = contact . is_primary ;
}
2013-12-07 19:45:00 +01:00
clientMap [ client . public_id ] = client ;
2013-12-30 21:17:45 +01:00
$clientSelect . append ( new Option ( getClientDisplayName ( client ), client . public_id ));
2013-12-07 19:45:00 +01:00
}
2013-11-27 08:38:37 +01:00
2013-12-29 00:33:48 +01:00
window . model = new InvoiceModel ();
@ foreach ( $taxRates as $taxRate )
model . addTaxRate ({{ $taxRate }});
@ endforeach
2013-12-29 12:28:44 +01:00
model . addTaxRate ();
2013-12-13 10:13:57 +01:00
@ if ( $invoice )
var invoice = {{ $invoice }};
2013-12-29 00:33:48 +01:00
ko . mapping . fromJS ( invoice , model . mapping , model );
2013-12-13 10:13:57 +01:00
if ( ! model . discount ()) model . discount ( '' );
var invitationContactIds = {{ json_encode ( $invitationContactIds ) }};
var client = clientMap [ invoice . client . public_id ];
for ( var i = 0 ; i < client . contacts . length ; i ++ ) {
var contact = client . contacts [ i ];
contact . send_invoice = invitationContactIds . indexOf ( contact . public_id ) >= 0 ;
}
@ else
2013-12-30 21:17:45 +01:00
model . invoice_date ( '{{ date(' Y - m - d ') }}' );
2013-12-15 13:55:50 +01:00
model . invoice_number ( '{{ $invoiceNumber }}' );
2013-12-30 21:17:45 +01:00
model . terms ( wordWrapText ( '{{ $account->invoice_terms }}' , 340 ));
2013-12-29 00:33:48 +01:00
@ endif
model . addItem ();
2013-11-26 13:45:07 +01:00
ko . applyBindings ( model );
</ script >
@ stop