Display client signature on the PDF #1504

This commit is contained in:
Hillel Coren 2017-12-27 12:54:50 +02:00
parent a49ee21b9b
commit 91e536503b
8 changed files with 96 additions and 7 deletions

View File

@ -906,6 +906,7 @@ class Invoice extends EntityModel implements BalanceAffecting
'documents',
'expenses',
'client',
'invitations',
'tax_name1',
'tax_rate1',
'tax_name2',
@ -988,8 +989,18 @@ class Invoice extends EntityModel implements BalanceAffecting
'invoice_fields',
'show_currency_code',
'inclusive_taxes',
'date_format',
'datetime_format',
'timezone',
]);
foreach ($this->invitations as $invitation) {
$invitation->setVisible([
'signature_base64',
'signature_date',
]);
}
foreach ($this->invoice_items as $invoiceItem) {
$invoiceItem->setVisible([
'product_key',

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,6 @@ NINJA.TEMPLATES = {
};
function GetPdfMake(invoice, javascript, callback) {
var itemsTable = false;
if (invoice.hasTasks) {
// check if we need to add a second table for tasks
@ -252,6 +251,8 @@ NINJA.decodeJavascript = function(invoice, javascript)
'fontSizeSmaller': NINJA.fontSize - 1,
'bodyFont': NINJA.bodyFont,
'headerFont': NINJA.headerFont,
'signatureBase64': NINJA.signatureImage(invoice),
'signatureDate': NINJA.signatureDate(invoice),
}
for (var key in json) {
@ -358,6 +359,33 @@ NINJA.decodeJavascript = function(invoice, 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)
{
if (invoice.is_delivery_note) {

View File

@ -31,6 +31,13 @@ function generatePDF(invoice, javascript, force, cb) {
}
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);
if (cb) {

View File

@ -2639,6 +2639,7 @@ $LANG = array(
'view_project' => 'View Project',
'summary' => 'Summary',
'endless_reminder' => 'Endless Reminder',
'signature_on_invoice_help' => 'Add the following code to show your client\'s signature on the PDF.'
);

View File

@ -234,11 +234,29 @@
<div class="panel panel-default">
<div class="panel-body">
{!! trans('texts.customize_help') !!}<br/>
<pre id="sampleData" style="display:none;height:200px;padding-top:16px;"></pre>
@if (empty($sampleInvoice))
<div class="help-block">{{ trans('texts.create_invoice_for_sample') }}</div>
@endif
@if ($account->require_invoice_signature || $account->require_invoice_signature)
<p>&nbsp;</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>

View File

@ -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">
<canvas id="theCanvas" style="max-width:100%;border:solid 1px #CCCCCC;"></canvas>
</div>
<canvas id="signatureCanvas" style="display:none;"></canvas>
@endif
@if (!Utils::isNinja() || !Utils::isPro())
@ -180,4 +181,27 @@
$('#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>