mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-18 00:53:10 +01:00
Working on PDF attachments
This commit is contained in:
parent
dc6ed9fca1
commit
b2678220c3
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,6 +8,7 @@
|
|||||||
/public/build
|
/public/build
|
||||||
/public/packages
|
/public/packages
|
||||||
/public/vendor
|
/public/vendor
|
||||||
|
/storage
|
||||||
/bootstrap/compiled.php
|
/bootstrap/compiled.php
|
||||||
/bootstrap/environment.php
|
/bootstrap/environment.php
|
||||||
/vendor
|
/vendor
|
||||||
|
@ -4,6 +4,7 @@ use Auth;
|
|||||||
use DB;
|
use DB;
|
||||||
use Datatable;
|
use Datatable;
|
||||||
use Utils;
|
use Utils;
|
||||||
|
use View;
|
||||||
|
|
||||||
class ActivityController extends BaseController
|
class ActivityController extends BaseController
|
||||||
{
|
{
|
||||||
@ -19,7 +20,14 @@ class ActivityController extends BaseController
|
|||||||
->addColumn('id', function ($model) { return Utils::timestampToDateTimeString(strtotime($model->created_at)); })
|
->addColumn('id', function ($model) { return Utils::timestampToDateTimeString(strtotime($model->created_at)); })
|
||||||
->addColumn('message', function ($model) { return Utils::decodeActivity($model->message); })
|
->addColumn('message', function ($model) { return Utils::decodeActivity($model->message); })
|
||||||
->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id); })
|
->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id); })
|
||||||
->addColumn('adjustment', function ($model) { return $model->adjustment != 0 ? Utils::formatMoney($model->adjustment, $model->currency_id) : ''; })
|
->addColumn('adjustment', function ($model) { return $model->adjustment != 0 ? self::wrapAdjustment($model->adjustment, $model->currency_id) : ''; })
|
||||||
->make();
|
->make();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function wrapAdjustment($adjustment, $currencyId)
|
||||||
|
{
|
||||||
|
$class = $adjustment <= 0 ? 'success' : 'default';
|
||||||
|
$adjustment = Utils::formatMoney($adjustment, $currencyId);
|
||||||
|
return "<h4><div class=\"label label-{$class}\">$adjustment</div></h4>";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ use DB;
|
|||||||
use Event;
|
use Event;
|
||||||
use URL;
|
use URL;
|
||||||
use Datatable;
|
use Datatable;
|
||||||
|
use finfo;
|
||||||
|
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Models\Invitation;
|
use App\Models\Invitation;
|
||||||
@ -440,12 +441,10 @@ class InvoiceController extends BaseController
|
|||||||
Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT, $url);
|
Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT, $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
This causes an error message. Commenting out. will return later.
|
|
||||||
if (!empty(Input::get('pdfupload')) && strpos(Input::get('pdfupload'), 'data:application/pdf;base64,') === 0) {
|
if (!empty(Input::get('pdfupload')) && strpos(Input::get('pdfupload'), 'data:application/pdf;base64,') === 0) {
|
||||||
$this->storePDF(Input::get('pdfupload'), $invoice->id);
|
$this->storePDF(Input::get('pdfupload'), $invoice->id);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
if ($action == 'clone') {
|
if ($action == 'clone') {
|
||||||
return $this->cloneInvoice($publicId);
|
return $this->cloneInvoice($publicId);
|
||||||
} elseif ($action == 'convert') {
|
} elseif ($action == 'convert') {
|
||||||
@ -594,12 +593,6 @@ class InvoiceController extends BaseController
|
|||||||
$uploadsDir = storage_path().'/pdfcache/';
|
$uploadsDir = storage_path().'/pdfcache/';
|
||||||
$encodedString = str_replace('data:application/pdf;base64,', '', $encodedString);
|
$encodedString = str_replace('data:application/pdf;base64,', '', $encodedString);
|
||||||
$name = 'cache-'.$invoiceId.'.pdf';
|
$name = 'cache-'.$invoiceId.'.pdf';
|
||||||
|
file_put_contents($uploadsDir.$name, base64_decode($encodedString));
|
||||||
if (file_put_contents($uploadsDir.$name, base64_decode($encodedString)) !== false) {
|
|
||||||
$finfo = new finfo(FILEINFO_MIME);
|
|
||||||
if ($finfo->file($uploadsDir.$name) !== 'application/pdf; charset=binary') {
|
|
||||||
unlink($uploadsDir.$name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,12 @@ class Invoice extends EntityModel
|
|||||||
return $this->invoice_number;
|
return $this->invoice_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getFileName()
|
||||||
|
{
|
||||||
|
$entityType = $this->getEntityType();
|
||||||
|
return trans("texts.$entityType") . '_' . $this->invoice_number . '.pdf';
|
||||||
|
}
|
||||||
|
|
||||||
public function getLink()
|
public function getLink()
|
||||||
{
|
{
|
||||||
return link_to('invoices/'.$this->public_id, $this->invoice_number);
|
return link_to('invoices/'.$this->public_id, $this->invoice_number);
|
||||||
|
@ -44,7 +44,7 @@ class ContactMailer extends Mailer
|
|||||||
$data['body'] = str_replace(array_keys($variables), array_values($variables), $emailTemplate);
|
$data['body'] = str_replace(array_keys($variables), array_values($variables), $emailTemplate);
|
||||||
$data['link'] = $invitation->getLink();
|
$data['link'] = $invitation->getLink();
|
||||||
$data['entityType'] = $entityType;
|
$data['entityType'] = $entityType;
|
||||||
$data['id'] = $invoice->getAttributes()['id'];
|
$data['invoice_id'] = $invoice->id;
|
||||||
|
|
||||||
$fromEmail = $invitation->user->email;
|
$fromEmail = $invitation->user->email;
|
||||||
$this->sendTo($invitation->contact->email, $fromEmail, $accountName, $subject, $view, $data);
|
$this->sendTo($invitation->contact->email, $fromEmail, $accountName, $subject, $view, $data);
|
||||||
|
@ -21,16 +21,13 @@ class Mailer
|
|||||||
$fromEmail = NINJA_FROM_EMAIL;
|
$fromEmail = NINJA_FROM_EMAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isset($data['id'])) {
|
if(isset($data['invoice_id'])) {
|
||||||
$invoice = Invoice::find($data['id']);
|
$invoice = Invoice::scope($data['invoice_id'])->with(['account'])->first();
|
||||||
$invoice->load('account');
|
|
||||||
$accountAttributes = $invoice->account()->getParent()->getRelations()['account']->getAttributes();
|
|
||||||
$pdfPath = storage_path().'/pdfcache/cache-'.$invoice->id.'.pdf';
|
$pdfPath = storage_path().'/pdfcache/cache-'.$invoice->id.'.pdf';
|
||||||
|
if($invoice->account->pdf_email_attachment && file_exists($pdfPath)) {
|
||||||
if($accountAttributes['pdf_email_attachment'] === 1 && file_exists($pdfPath)) {
|
|
||||||
$message->attach(
|
$message->attach(
|
||||||
$pdfPath,
|
$pdfPath,
|
||||||
array('as' => $accountAttributes['name'].'_'.$accountAttributes['invoice_number_prefix'].$invoice->getName().'.pdf', 'mime' => 'application/pdf')
|
array('as' => $invoice->getFileName(), 'mime' => 'application/pdf')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
public/css/built.css
vendored
8
public/css/built.css
vendored
@ -2443,4 +2443,10 @@ div.checkbox > label {
|
|||||||
.panel-default {
|
.panel-default {
|
||||||
border-color: #e37329 !important;
|
border-color: #e37329 !important;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.alert-hide {
|
||||||
|
position: absolute;
|
||||||
|
margin-left: 25%;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
8
public/css/style.css
vendored
8
public/css/style.css
vendored
@ -846,4 +846,10 @@ div.checkbox > label {
|
|||||||
.panel-default {
|
.panel-default {
|
||||||
border-color: #e37329 !important;
|
border-color: #e37329 !important;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.alert-hide {
|
||||||
|
position: absolute;
|
||||||
|
margin-left: 25%;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
@ -213,6 +213,10 @@
|
|||||||
|
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
window.setTimeout(function() {
|
||||||
|
$(".alert-hide").fadeOut(500);
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
$('#search').focus(function(){
|
$('#search').focus(function(){
|
||||||
if (!window.hasOwnProperty('searchData')) {
|
if (!window.hasOwnProperty('searchData')) {
|
||||||
$.get('{{ URL::route('getSearchData') }}', function(data) {
|
$.get('{{ URL::route('getSearchData') }}', function(data) {
|
||||||
@ -410,7 +414,7 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (Session::has('message'))
|
@if (Session::has('message'))
|
||||||
<div class="alert alert-info">
|
<div class="alert alert-info alert-hide">
|
||||||
{{ Session::get('message') }}
|
{{ Session::get('message') }}
|
||||||
</div>
|
</div>
|
||||||
@elseif (Session::has('news_feed_message'))
|
@elseif (Session::has('news_feed_message'))
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
<div data-bind="with: invoice">
|
<div data-bind="with: invoice">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-body">
|
<div class="panel-body" style="padding-bottom: 0px;">
|
||||||
|
|
||||||
<div class="row" style="min-height:195px" onkeypress="formEnterClick(event)">
|
<div class="row" style="min-height:195px" onkeypress="formEnterClick(event)">
|
||||||
<div class="col-md-4" id="col_1">
|
<div class="col-md-4" id="col_1">
|
||||||
@ -129,8 +129,6 @@
|
|||||||
|
|
||||||
<p> </p>
|
<p> </p>
|
||||||
|
|
||||||
{!! Former::hidden('data')->data_bind("value: ko.mapping.toJSON(model)") !!}
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table invoice-table" style="margin-bottom: 0px !important">
|
<table class="table invoice-table" style="margin-bottom: 0px !important">
|
||||||
<thead>
|
<thead>
|
||||||
@ -151,8 +149,8 @@
|
|||||||
<i style="display:none" data-bind="visible: actionsVisible() && $parent.invoice_items().length > 1" class="fa fa-sort"></i>
|
<i style="display:none" data-bind="visible: actionsVisible() && $parent.invoice_items().length > 1" class="fa fa-sort"></i>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{!! Former::text('product_key')->useDatalist($products->toArray(), 'product_key')->onkeyup('onItemChange()')
|
{!! Former::text('product_key')->useDatalist($products->toArray(), 'product_key')->onkeyup('onItemChange()')
|
||||||
->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') !!}
|
->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') !!}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<textarea data-bind="value: wrapped_notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" style="resize: none;" class="form-control word-wrap"></textarea>
|
<textarea data-bind="value: wrapped_notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" style="resize: none;" class="form-control word-wrap"></textarea>
|
||||||
@ -299,6 +297,8 @@
|
|||||||
{!! Former::populateField('entityType', $entityType) !!}
|
{!! Former::populateField('entityType', $entityType) !!}
|
||||||
{!! Former::text('entityType') !!}
|
{!! Former::text('entityType') !!}
|
||||||
{!! Former::text('action') !!}
|
{!! Former::text('action') !!}
|
||||||
|
{!! Former::text('data')->data_bind("value: ko.mapping.toJSON(model)") !!}
|
||||||
|
{!! Former::text('pdfupload') !!}
|
||||||
|
|
||||||
@if ($invoice && $invoice->id)
|
@if ($invoice && $invoice->id)
|
||||||
{!! Former::populateField('id', $invoice->public_id) !!}
|
{!! Former::populateField('id', $invoice->public_id) !!}
|
||||||
@ -308,9 +308,9 @@
|
|||||||
|
|
||||||
|
|
||||||
@if (!Utils::isPro() || \App\Models\InvoiceDesign::count() == COUNT_FREE_DESIGNS)
|
@if (!Utils::isPro() || \App\Models\InvoiceDesign::count() == COUNT_FREE_DESIGNS)
|
||||||
{!! 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') !!}
|
{!! Former::select('invoice_design_id')->style('display:'.($account->utf8_invoices ? 'none' : 'inline').';width:150px;background-color:white !important')->raw()->fromQuery($invoiceDesigns, 'name', 'id')->data_bind("value: invoice_design_id")->addOption(trans('texts.more_designs') . '...', '-1') !!}
|
||||||
@else
|
@else
|
||||||
{!! 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") !!}
|
{!! Former::select('invoice_design_id')->style('display:'.($account->utf8_invoices ? 'none' : 'inline').';width:150px;background-color:white !important')->raw()->fromQuery($invoiceDesigns, 'name', 'id')->data_bind("value: invoice_design_id") !!}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{!! Button::primary(trans('texts.download_pdf'))->withAttributes(array('onclick' => 'onDownloadClick()'))->appendIcon(Icon::create('download-alt')) !!}
|
{!! Button::primary(trans('texts.download_pdf'))->withAttributes(array('onclick' => 'onDownloadClick()'))->appendIcon(Icon::create('download-alt')) !!}
|
||||||
@ -674,7 +674,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
@if (Auth::user()->account->fill_products)
|
@if (Auth::user()->account->fill_products)
|
||||||
$('.datalist').on('input', function() {
|
$('.datalist').on('change', function() {
|
||||||
var key = $(this).val();
|
var key = $(this).val();
|
||||||
for (var i=0; i<products.length; i++) {
|
for (var i=0; i<products.length; i++) {
|
||||||
var product = products[i];
|
var product = products[i];
|
||||||
@ -746,7 +746,7 @@
|
|||||||
|
|
||||||
function onEmailClick() {
|
function onEmailClick() {
|
||||||
if (confirm('{{ trans("texts.confirm_email_$entityType") }}')) {
|
if (confirm('{{ trans("texts.confirm_email_$entityType") }}')) {
|
||||||
submitAction('email');
|
preparePdfData('email');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -756,19 +756,22 @@
|
|||||||
submitAction('');
|
submitAction('');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var invoice = createInvoiceModel();
|
preparePdfData('');
|
||||||
var design = getDesignJavascript();
|
|
||||||
if (!design) return;
|
|
||||||
|
|
||||||
doc = generatePDF(invoice, design, true);
|
|
||||||
doc.getDataUrl( function(pdfString){
|
|
||||||
$('form.form-horizontal.warn-on-exit').append('<input type="hidden" name="pdfupload" value="'+pdfString+'">');
|
|
||||||
submitAction('');
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function preparePdfData(action) {
|
||||||
|
var invoice = createInvoiceModel();
|
||||||
|
var design = getDesignJavascript();
|
||||||
|
if (!design) return;
|
||||||
|
|
||||||
|
doc = generatePDF(invoice, design, true);
|
||||||
|
doc.getDataUrl( function(pdfString){
|
||||||
|
$('#pdfupload').val(pdfString);
|
||||||
|
submitAction(action);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function submitAction(value) {
|
function submitAction(value) {
|
||||||
if (!isSaveValid()) {
|
if (!isSaveValid()) {
|
||||||
model.showClientForm();
|
model.showClientForm();
|
||||||
@ -1116,7 +1119,7 @@
|
|||||||
self.invoice_items = ko.observableArray();
|
self.invoice_items = ko.observableArray();
|
||||||
self.amount = ko.observable(0);
|
self.amount = ko.observable(0);
|
||||||
self.balance = ko.observable(0);
|
self.balance = ko.observable(0);
|
||||||
self.invoice_design_id = ko.observable({{ $account->invoice_design_id }});
|
self.invoice_design_id = ko.observable({{ $account->utf8_invoices ? 1 : $account->invoice_design_id }});
|
||||||
self.partial = ko.observable(0);
|
self.partial = ko.observable(0);
|
||||||
self.is_partial = ko.observable(false);
|
self.is_partial = ko.observable(false);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user