mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Display client signature on the PDF #1504
This commit is contained in:
parent
a49ee21b9b
commit
91e536503b
@ -906,6 +906,7 @@ class Invoice extends EntityModel implements BalanceAffecting
|
|||||||
'documents',
|
'documents',
|
||||||
'expenses',
|
'expenses',
|
||||||
'client',
|
'client',
|
||||||
|
'invitations',
|
||||||
'tax_name1',
|
'tax_name1',
|
||||||
'tax_rate1',
|
'tax_rate1',
|
||||||
'tax_name2',
|
'tax_name2',
|
||||||
@ -988,8 +989,18 @@ class Invoice extends EntityModel implements BalanceAffecting
|
|||||||
'invoice_fields',
|
'invoice_fields',
|
||||||
'show_currency_code',
|
'show_currency_code',
|
||||||
'inclusive_taxes',
|
'inclusive_taxes',
|
||||||
|
'date_format',
|
||||||
|
'datetime_format',
|
||||||
|
'timezone',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
foreach ($this->invitations as $invitation) {
|
||||||
|
$invitation->setVisible([
|
||||||
|
'signature_base64',
|
||||||
|
'signature_date',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($this->invoice_items as $invoiceItem) {
|
foreach ($this->invoice_items as $invoiceItem) {
|
||||||
$invoiceItem->setVisible([
|
$invoiceItem->setVisible([
|
||||||
'product_key',
|
'product_key',
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -14,7 +14,6 @@ NINJA.TEMPLATES = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function GetPdfMake(invoice, javascript, callback) {
|
function GetPdfMake(invoice, javascript, callback) {
|
||||||
|
|
||||||
var itemsTable = false;
|
var itemsTable = false;
|
||||||
if (invoice.hasTasks) {
|
if (invoice.hasTasks) {
|
||||||
// check if we need to add a second table for tasks
|
// check if we need to add a second table for tasks
|
||||||
@ -252,6 +251,8 @@ NINJA.decodeJavascript = function(invoice, javascript)
|
|||||||
'fontSizeSmaller': NINJA.fontSize - 1,
|
'fontSizeSmaller': NINJA.fontSize - 1,
|
||||||
'bodyFont': NINJA.bodyFont,
|
'bodyFont': NINJA.bodyFont,
|
||||||
'headerFont': NINJA.headerFont,
|
'headerFont': NINJA.headerFont,
|
||||||
|
'signatureBase64': NINJA.signatureImage(invoice),
|
||||||
|
'signatureDate': NINJA.signatureDate(invoice),
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in json) {
|
for (var key in json) {
|
||||||
@ -358,6 +359,33 @@ NINJA.decodeJavascript = function(invoice, javascript)
|
|||||||
return javascript;
|
return javascript;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NINJA.signatureImage = function(invoice) {
|
||||||
|
var blankImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=';
|
||||||
|
|
||||||
|
if (! invoice.invitations || ! invoice.invitations.length) {
|
||||||
|
return blankImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
return invoice.invitations[0].signature_base64 || blankImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
NINJA.signatureDate = function(invoice) {
|
||||||
|
if (! invoice.invitations || ! invoice.invitations.length) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var date = invoice.invitations[0].signature_date;
|
||||||
|
|
||||||
|
return NINJA.formatDateTime(date, invoice.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
NINJA.formatDateTime = function(date, account) {
|
||||||
|
var format = account.datetime_format ? account.datetime_format.format_moment : 'LLL';
|
||||||
|
var timezone = account.timezone ? account.timezone.name : '{{ DEFAULT_TIMEZONE }}';
|
||||||
|
|
||||||
|
return date ? moment.utc(date).tz(timezone).format(format) : '';
|
||||||
|
}
|
||||||
|
|
||||||
NINJA.entityType = function(invoice)
|
NINJA.entityType = function(invoice)
|
||||||
{
|
{
|
||||||
if (invoice.is_delivery_note) {
|
if (invoice.is_delivery_note) {
|
||||||
|
@ -31,6 +31,13 @@ function generatePDF(invoice, javascript, force, cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
invoice = calculateAmounts(invoice);
|
invoice = calculateAmounts(invoice);
|
||||||
|
invoice = convertSignature(invoice);
|
||||||
|
|
||||||
|
// convertSignature returns false to wait for the canvas to draw
|
||||||
|
if (! invoice) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var pdfDoc = GetPdfMake(invoice, javascript, cb);
|
var pdfDoc = GetPdfMake(invoice, javascript, cb);
|
||||||
|
|
||||||
if (cb) {
|
if (cb) {
|
||||||
|
@ -2639,6 +2639,7 @@ $LANG = array(
|
|||||||
'view_project' => 'View Project',
|
'view_project' => 'View Project',
|
||||||
'summary' => 'Summary',
|
'summary' => 'Summary',
|
||||||
'endless_reminder' => 'Endless Reminder',
|
'endless_reminder' => 'Endless Reminder',
|
||||||
|
'signature_on_invoice_help' => 'Add the following code to show your client\'s signature on the PDF.'
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -234,11 +234,29 @@
|
|||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
{!! trans('texts.customize_help') !!}<br/>
|
{!! trans('texts.customize_help') !!}<br/>
|
||||||
|
|
||||||
<pre id="sampleData" style="display:none;height:200px;padding-top:16px;"></pre>
|
<pre id="sampleData" style="display:none;height:200px;padding-top:16px;"></pre>
|
||||||
@if (empty($sampleInvoice))
|
@if (empty($sampleInvoice))
|
||||||
<div class="help-block">{{ trans('texts.create_invoice_for_sample') }}</div>
|
<div class="help-block">{{ trans('texts.create_invoice_for_sample') }}</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if ($account->require_invoice_signature || $account->require_invoice_signature)
|
||||||
|
<p> </p>
|
||||||
|
{{ trans('texts.signature_on_invoice_help') }}
|
||||||
|
<pre style="padding-top:16px;">
|
||||||
|
{
|
||||||
|
"stack": [
|
||||||
|
{
|
||||||
|
"image": "$signatureBase64",
|
||||||
|
"margin": [200, 10, 0, 0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "$signatureDate",
|
||||||
|
"margin": [200, -40, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
</pre>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<div id="pdfCanvas" style="display:none;width:100%;background-color:#525659;border:solid 2px #9a9a9a;padding-top:40px;text-align:center">
|
<div id="pdfCanvas" style="display:none;width:100%;background-color:#525659;border:solid 2px #9a9a9a;padding-top:40px;text-align:center">
|
||||||
<canvas id="theCanvas" style="max-width:100%;border:solid 1px #CCCCCC;"></canvas>
|
<canvas id="theCanvas" style="max-width:100%;border:solid 1px #CCCCCC;"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
<canvas id="signatureCanvas" style="display:none;"></canvas>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (!Utils::isNinja() || !Utils::isPro())
|
@if (!Utils::isNinja() || !Utils::isPro())
|
||||||
@ -180,4 +181,27 @@
|
|||||||
$('#moreDesignsModal').modal('show');
|
$('#moreDesignsModal').modal('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function convertSignature(invoice) {
|
||||||
|
if (! invoice || ! invoice.invitations || ! invoice.invitations.length) {
|
||||||
|
return invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
var sourceSVG = invoice.invitations[0].signature_base64;
|
||||||
|
if (! sourceSVG || sourceSVG.indexOf('data:image') == 0) {
|
||||||
|
return invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
var signatureDiv = $('#signatureCanvas')[0];
|
||||||
|
var ctx = signatureDiv.getContext('2d');
|
||||||
|
var img = new Image();
|
||||||
|
img.src = "data:image/svg+xml;base64," + sourceSVG;
|
||||||
|
img.onload = function() {
|
||||||
|
ctx.drawImage(img, 0, 0);
|
||||||
|
invoice.invitations[0].signature_base64 = signatureDiv.toDataURL("image/png");
|
||||||
|
refreshPDF();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user