return new Promise(function (resolve, reject) { if (meta.project_type_class === "standard") { // normalize input var chapters = _.mapValues(_.groupBy(translation, function (obj) { //console.debug('map chapter values', obj); return obj.chunkmeta.chapterid; }), function (chapter, key) { var frames = _.mapKeys(chapter, function (obj) { //console.debug('map chapter keys', obj); return obj.chunkmeta.frameid; }); var chapterObj = { id: key, title: frames.title || key, reference: frames.reference === undefined ? null : frames.reference, format: meta.format }; delete frames.reference; delete frames.title; chapterObj.frames = _.sortBy(_.filter(frames, function (o) { return o.transcontent !== ''; }), function (f) { //console.debug('sort frames',f); return f.chunkmeta.frame; }); return chapterObj; }); var project = { format: meta.format, title: chapters['00'].title }; delete chapters['00']; project.chapters = _.sortBy(_.filter(chapters, function (o) { return o.frames.length > 0; }), 'id'); chapters = null; if (project.format === 'markdown') { var doc = new PDFDocument({ bufferPages: true, margins:{ top: 72, bottom: 50, left: 72, right: 72 } }); doc.pipe(fs.createWriteStream(filePath)); // default meta if (project.title.transcontent !== "") { doc.info.Title = project.title.transcontent; } else { doc.info.Title = project.title.projectmeta.project.name; } //doc.info.Author = 'Joel Lonbeck'; // todo: translators //doc.info.Subject = 'an unrestricted, visual mini-Bible in any language'; // todo: project sub-title doc.info.Keywords = meta.target_language.name; // book title doc.fontSize(25) .font(targetfont) .text(doc.info.Title, 72, doc.page.height / 2, {align: 'center'}); mythis.renderLicense(doc, "OBS_LICENSE.md"); // TOC placeholders doc.addPage(); var lastTOCPage = doc.bufferedPageRange().count; var tocPages = { start: lastTOCPage - 1 }; doc.fontSize(25) .text(' ', 72, 72) .moveDown(); _.forEach(project.chapters, function (chapter) { doc.fontSize(10) .text(' ') .moveDown(); var currPage = doc.bufferedPageRange().count; if (lastTOCPage !== currPage) { // record toc page split tocPages[chapter.id] = currPage - 1; lastTOCPage = currPage; // give room for header on new page doc.fontSize(25) .text(' ', 72, 72) .moveDown(); } }); // book body _.forEach(project.chapters, function (chapter) { // chapter title doc.addPage(); doc.fontSize(20) .text(chapter.title.transcontent || chapter.title.chunkmeta.title, 72, doc.page.height / 2, {align: 'center'}); chapter.page = doc.bufferedPageRange().count; // frames if (options.doubleSpace === true) { doc.lineGap(20); } doc.addPage(); _.forEach(chapter.frames, function (frame) { if (options.includeIncompleteFrames === true || frame.completed === true) { doc.moveDown(); if (options.includeImages === true) { //console.debug(meta); //console.debug(frame); // TRICKY: right now all images are en var imgPath = path.join(imagePath, meta.resource.id + "-en-" + frame.chunkmeta.chapterid + "-" + frame.chunkmeta.frameid + ".jpg"); //check the position of the text on the page. // 792 (total ht of page) - 50 ( lower margin) - 263.25 (height of pic) = 478.75 (max amount of space used before image) if (doc.y > 478.75) { doc.addPage(); } doc.image(imgPath, {width:doc.page.width - 72*2}); } doc.fontSize(10) .text(frame.transcontent); if (options.includeImages === true) { doc.moveDown();//add extra line break after image and text as per github issue527 } } }); // chapter reference if (chapter.reference !== null) { doc.moveDown() .fontSize(10) .text(chapter.reference.transcontent); } }); // number pages var range = doc.bufferedPageRange(); for (var i = range.start; i < range.start + range.count; i ++) { doc.switchToPage(i); doc.fontSize(10) .font(defaultfont) .text(i + 1, 72, doc.page.height - 50 - 12, {align: 'center'}); } // write TOC var currTocPage = tocPages.start; doc.switchToPage(currTocPage); // TODO: display correct title of TOC based on the project doc.fontSize(25) .lineGap(0) .text('Table of Contents', 72, 72) .font(targetfont) .moveDown(); _.forEach(project.chapters, function (chapter) { if (tocPages[chapter.id] !== undefined && tocPages[chapter.id] !== currTocPage) { currTocPage = tocPages[chapter.id]; doc.switchToPage(currTocPage); doc.fontSize(10) .text(' ') .moveUp(); } doc.switchToPage(currTocPage); doc.fontSize(10) .text(chapter.title.transcontent || chapter.title.chunkmeta.title) .moveUp() .text(chapter.page + '', {align: 'right'}) .moveDown(); }); doc.end(); resolve(true); } else if (project.format === 'usfm') { var doc = new PDFDocument({ bufferPages: true, margins:{ top: 72, bottom: 50, left: 72, right: 72 } }); doc.pipe(fs.createWriteStream(filePath)); //set the title doc.info.Title = translation[0].transcontent || meta.project.name; doc.fontSize(25) .font(targetfont) .text(doc.info.Title, 72, doc.page.height / 2, {align: 'center'}); mythis.renderLicense(doc, "LICENSE.md"); // book body _.forEach(project.chapters, function (chapter) { doc.addPage();//start each chapter on new page //list chapters (remove leading zeros in the numbers) var chapterNum = chapter.id.replace(/\b0+/, ''); doc.fontSize(20) .lineGap(10) .text(chapterNum + ' ', {continued: true}); chapter.page = doc.bufferedPageRange().count; // frames if (options.doubleSpace === true) { doc.lineGap(20); } _.forEach(chapter.frames, function (frame) { if (options.includeIncompleteFrames === true || frame.completed === true) { var content = frame.transcontent.split(/[\\]*[\\||\/][v][ ]([0-9]+)/g); _.forEach(content, function (info) { let output = info; //superscript for verses not supported by pdfkit: https://github.com/devongovett/pdfkit/issues/15 output = output.replace(/[\\][\\c][ ][0-9]+ /g, ''); doc.fontSize(10) .text(output + ' ', { continued: true}); }); } doc.moveDown() .text(""); }); }); // number pages var range = doc.bufferedPageRange(); for (var i = range.start; i < range.start + range.count; i ++) { doc.switchToPage(i); doc.fontSize(10) .font(defaultfont) .text(i + 1, 72, doc.page.height - 50 - 12, {align: 'center'}); } doc.end(); resolve(true); } else { reject('We only support printing OBS and Bible projects for now'); } } else { // TODO: support exporting other target translation types if needed e.g. notes, words, questions reject('We do not support printing that project type yet'); } });
var findTests = function(error, tests){ //Handle Error. if(error){ return next(error); } //Create a pdf document var doc = new PDFKit({bufferPages: true}); var stream = doc.pipe(res); //First page (Build infos) doc.fillColor('black').fontSize(30).text('Build Report'); doc.moveDown(); doc.fontSize(15).text('Build Name', {underline:true, continued: true}).text(': '+build.name, {underline:false}); doc.moveDown(); doc.fontSize(15).text('Date', {underline:true, continued: true}).text(': '+build.date, {underline:false}); doc.moveDown(); if(!_.isNull(build.duration.value)){ doc.fontSize(15).text('Duration', {underline:true, continued: true}).text(': '+batam_util.durationToStr(build.duration.value), {underline:false}); }else{ doc.fontSize(15).text('Duration', {underline:true, continued: true}).text(': Not Available', {underline:false}); } doc.moveDown(); doc.fontSize(15).text('Total Tests', {underline:true, continued: true}).text(': '+build.tests.value, {underline:false}); doc.moveDown(); doc.fontSize(15).text('Passes', {underline:true, continued: true}).text(': '+build.passes.value, {underline:false}); doc.moveDown(); if(!_.isUndefined(build.regressions) && !_.isUndefined(build.regressions.value)){ doc.fontSize(15).text('Regressions', {underline:true, continued: true}).text(': '+build.regressions.value, {underline:false}); }else{ doc.fontSize(15).text('Regressions', {underline:true, continued: true}).text(': Not Available', {underline:false}); } doc.moveDown(); if(!_.isUndefined(build.failures) && !_.isUndefined(build.failures.value)){ doc.fontSize(15).text('Failures', {underline:true, continued: true}).text(': '+build.failures.value, {underline:false}); }else{ doc.fontSize(15).text('Failures', {underline:true, continued: true}).text(': Not Available', {underline:false}); } doc.moveDown(); if(!_.isUndefined(build.errors) && !_.isUndefined(build.errors.value)){ doc.fontSize(15).text('Errors', {underline:true, continued: true}).text(': '+build.errors.value, {underline:false}); }else{ doc.fontSize(15).text('Errors', {underline:true, continued: true}).text(': Not Available', {underline:false}); } //Table of Content doc.addPage(); doc.fillColor('black').fontSize(20).text('Table of Content'); doc.moveDown(); //Summary doc.addPage(); var summaryPage = doc.bufferedPageRange().count -1; var initialYAxis = 150; doc.fontSize(30).fillColor('black').text('Summary'); doc.rect(75, initialYAxis, 200, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(275, initialYAxis, 50, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(325, initialYAxis, 50, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(375, initialYAxis, 50, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(425, initialYAxis, 50, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(475, initialYAxis, 50, 25).fillAndStroke("#F0F0F0", "black"); doc.fontSize(8).fillColor('black').text('Functional Areas', 80, initialYAxis + 5); doc.fontSize(8).fillColor('black').text('Tests', 280, initialYAxis + 5); doc.fontSize(8).fillColor('black').text('Passes', 330, initialYAxis + 5); doc.fontSize(8).fillColor('black').text('Regressions', 380, initialYAxis + 5); doc.fontSize(8).fillColor('black').text('Failures', 430, initialYAxis + 5); doc.fontSize(8).fillColor('black').text('Errors', 480, initialYAxis + 5); var totalTests = 0; var totalPasses = 0; var totalRegressions = 0; var totalFailures = 0; var totalErrors = 0; var rowPerPage = 20; var pageIndex = 1; for(var i = 1; i <= reports.length; i++){ if(pageIndex % rowPerPage == 0){ doc.addPage(); pageIndex = 1; rowPerPage = 25; initialYAxis = 50; } doc.rect(75, initialYAxis+(pageIndex*25), 200, 25).fillAndStroke("white", "black"); doc.rect(275, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("white", "black"); doc.rect(325, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("white", "black"); if(reports[i-1].tests.regressions.value != 0){ doc.rect(375, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(375, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#669966", "black"); } if(reports[i-1].tests.failures.value != 0){ doc.rect(425, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(425, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#669966", "black"); } if(reports[i-1].tests.errors.value != 0){ doc.rect(475, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(475, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#669966", "black"); } doc.fontSize(9).fillColor('black').text(reports[i-1].name, 80, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(reports[i-1].tests.all.value, 280, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(reports[i-1].tests.passes.value, 330, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(reports[i-1].tests.regressions.value, 380, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(reports[i-1].tests.failures.value, 430, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(reports[i-1].tests.errors.value, 480, initialYAxis+(pageIndex*25)+5); totalTests += reports[i-1].tests.all.value; totalPasses += reports[i-1].tests.passes.value; totalRegressions += reports[i-1].tests.regressions.value; totalFailures += reports[i-1].tests.failures.value; totalErrors += reports[i-1].tests.errors.value; pageIndex++; } doc.rect(75, initialYAxis+(pageIndex*25), 200, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(275, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("white", "black"); doc.rect(325, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("white", "black"); if(totalRegressions != 0){ doc.rect(375, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(375, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#669966", "black"); } if(totalFailures != 0){ doc.rect(425, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(425, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#669966", "black"); } if(totalErrors != 0){ doc.rect(475, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(475, initialYAxis+(pageIndex*25), 50, 25).fillAndStroke("#669966", "black"); } doc.fontSize(9).fillColor('black').text("Total", 80, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(totalTests, 280, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(totalPasses, 330, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(totalRegressions, 380, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(totalFailures, 430, initialYAxis+(pageIndex*25)+5); doc.fontSize(9).fillColor('black').text(totalErrors, 480, initialYAxis+(pageIndex*25)+5); //Tests results per reports doc.addPage(); var reportPage = doc.bufferedPageRange().count -1; doc.fontSize(30).fillColor('black').text('Results by Functional Area'); for(var i = 0; i < reports.length; i++){ doc.addPage(); doc.fontSize(20).fillColor('black').text(reports[i].name, {underline:false}); doc.moveDown(); doc.fontSize(10).fillColor('black').text('Tests', {underline:true, continued: true}).text(': '+reports[i].tests.all.value+", ", {underline:false, continued: true}) .text('Pass', {underline:true, continued: true}).text(': '+(reports[i].tests.all.value - reports[i].tests.regressions.value)+", ", {underline:false, continued: true}) .text('Failures', {underline:true, continued: true}).text(': '+reports[i].tests.regressions.value+", ", {underline:false, continued: true}) .text('Run Time', {underline:true, continued: true}).text(': '+batam_util.durationToStr(reports[i].duration.value), {underline:false}); doc.moveDown(); doc.fontSize(10).text(reports[i].description, {underline:false}); doc.rect(60, 200, 380, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(435, 200, 60, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(495, 200, 60, 25).fillAndStroke("#F0F0F0", "black"); doc.fontSize(8).fillColor('black').text('Test Name / Description', 65, 205); doc.fontSize(8).fillColor('black').text('Status', 440, 205); doc.fontSize(8).fillColor('black').text('Run Time', 500, 205); var rowPerPage = 9; initialYAxis = 175; var pageIndex = 1; for(var j = 0; j < tests.length; j++){ //fetch test that belongs to the current report if(tests[j].report_id == reports[i].id){ if(pageIndex % rowPerPage == 0){ doc.addPage(); pageIndex = 1; rowPerPage = 12; initialYAxis = 50; } if(tests[j].status != 'pass'){ doc.rect(60, initialYAxis+(pageIndex * 50), 5, 50).fillAndStroke("#990000", "black"); }else{ doc.rect(60, initialYAxis+(pageIndex * 50), 5, 50).fillAndStroke("#669966", "black"); } if(pageIndex % 2 == 0){ doc.rect(65, initialYAxis+(pageIndex * 50), 490, 50).fillAndStroke("white", "black"); }else{ doc.rect(65, initialYAxis+(pageIndex * 50), 490, 50).fillAndStroke("#F0F0F0", "black"); } if(tests[j].status != 'pass'){ doc.rect(435, initialYAxis+(pageIndex * 50), 60, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(435, initialYAxis+(pageIndex * 50), 60, 25).fillAndStroke("#669966", "black"); } doc.rect(495, initialYAxis+(pageIndex * 50), 60, 25).fillAndStroke("white", "black"); doc.fontSize(6).fillColor('black').text(tests[j].name, 70, initialYAxis + (pageIndex * 50) + 5); doc.fontSize(6).fillColor('black').text(tests[j].status, 440, initialYAxis + (pageIndex * 50) + 5); doc.fontSize(6).fillColor('black').text(batam_util.durationToStr(tests[j].duration.value), 500, initialYAxis + (pageIndex * 50) + 5); doc.fontSize(6).fillColor('black').text(tests[j].description == null ? "Description Not Available" : tests[j].description, 70, initialYAxis + (pageIndex * 50) + 30); var dynamicFields = 'Criterias: '; for(var field in tests[j]){ if(field != '_id' && field != 'description' && field != 'report_id' && field != 'name' && field != 'start_date' && field != 'end_date' && field != 'status' && field != 'time' && field != 'regression' && field != 'log' && field != 'duration' && field != 'steps' && field != 'report_name' && field != 'build_name' && field != 'build_id' && field != 'test_suite' && field != 'author' && field != 'previous_id' && field != 'next_id'){ dynamicFields += field+" "; } } doc.fontSize(6).fillColor('black').text(dynamicFields, 70, initialYAxis + (pageIndex * 50) + 40); pageIndex++; } } //Sub Total doc.rect(60, initialYAxis+(pageIndex * 50), 60, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(120, initialYAxis+(pageIndex * 50), 60, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(180, initialYAxis+(pageIndex * 50), 60, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(240, initialYAxis+(pageIndex * 50), 60, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(300, initialYAxis+(pageIndex * 50), 60, 25).fillAndStroke("#F0F0F0", "black"); doc.fontSize(9).fillColor('black').text('Total', 65, initialYAxis+(pageIndex * 50) + 5); doc.fontSize(9).fillColor('black').text('Pass', 125, initialYAxis+(pageIndex * 50) + 5); doc.fontSize(9).fillColor('black').text('Regressions', 185, initialYAxis+(pageIndex * 50) + 5); doc.fontSize(9).fillColor('black').text('Failues', 245, initialYAxis+(pageIndex * 50) + 5); doc.fontSize(9).fillColor('black').text('Errors', 305, initialYAxis+(pageIndex * 50) + 5); doc.rect(60, initialYAxis+((pageIndex + 1) * 50) - 25, 60, 25).fillAndStroke("white", "black"); doc.rect(120, initialYAxis+((pageIndex + 1) * 50) - 25, 60, 25).fillAndStroke("white", "black"); if(reports[i].tests.regressions.value != 0){ doc.rect(180, initialYAxis+((pageIndex + 1) * 50) - 25, 60, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(180, initialYAxis+((pageIndex + 1) * 50) - 25, 60, 25).fillAndStroke("#669966", "black"); } if(reports[i].tests.failures.value != 0){ doc.rect(240, initialYAxis+((pageIndex + 1) * 50) - 25, 60, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(240, initialYAxis+((pageIndex + 1) * 50) - 25, 60, 25).fillAndStroke("#669966", "black"); } if(reports[i].tests.errors.value != 0){ doc.rect(300, initialYAxis+((pageIndex + 1) * 50) - 25, 60, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(300, initialYAxis+((pageIndex + 1) * 50) - 25, 60, 25).fillAndStroke("#669966", "black"); } doc.fontSize(10).fillColor('black').text(reports[i].tests.all.value, 65, initialYAxis+((pageIndex + 1) * 50) - 25 + 5); doc.fontSize(10).fillColor('black').text(reports[i].tests.passes.value, 125, initialYAxis+((pageIndex + 1) * 50) - 25 + 5); doc.fontSize(10).fillColor('black').text(reports[i].tests.regressions.value, 185, initialYAxis+((pageIndex + 1) * 50) - 25 + 5); doc.fontSize(10).fillColor('black').text(reports[i].tests.failures.value, 245, initialYAxis+((pageIndex + 1) * 50) - 25 + 5); doc.fontSize(10).fillColor('black').text(reports[i].tests.errors.value, 305, initialYAxis+((pageIndex + 1) * 50) - 25 + 5); } //Failing test log messages doc.addPage(); var logPage = doc.bufferedPageRange().count -1; initialYAxis = 150; doc.fontSize(30).fillColor('black').text('Message Logs'); for(var i = 0; i < reports.length; i++){ doc.addPage(); doc.fontSize(20).fillColor('black').text(reports[i].name); doc.moveDown(); doc.fontSize(12).fillColor('black').text('Tests', {underline:true, continued: true}).text(': '+reports[i].tests.all.value, {underline:false}); doc.fontSize(12).fillColor('black').text('Pass', {underline:true, continued: true}).text(': '+(reports[i].tests.passes.value), {underline:false}); doc.fontSize(12).fillColor('black').text('Regressions', {underline:true, continued: true}).text(': '+(reports[i].tests.regressions.value), {underline:false}); doc.fontSize(12).fillColor('black').text('Failures', {underline:true, continued: true}).text(': '+reports[i].tests.failures.value, {underline:false}); doc.fontSize(12).fillColor('black').text('Errors', {underline:true, continued: true}).text(': '+reports[i].tests.errors.value, {underline:false}); doc.fontSize(12).fillColor('black').text('Run Time', {underline:true, continued: true}).text(': '+batam_util.durationToStr(reports[i].duration.value), {underline:false}); doc.moveDown(); doc.fontSize(9).text(reports[i].description == null ? "No description available" : reports[i].description, {underline:false}); for(var j = 0; j < tests.length; j++){ //fetch test that belongs to the current report if(tests[j].report_id == reports[i].id){ doc.addPage(); doc.fontSize(10).fillColor('black').text('Test Name', {underline:true, continued: true}).text(": "+tests[j].name, {underline:false}); doc.moveDown(); doc.fontSize(9).text(tests[j].description == null ? "No description available" : tests[j].description, {underline:false, continued: false}); doc.rect(100, initialYAxis+(0 * 25), 100, 25).fillAndStroke("#F0F0F0", "black"); if(tests[j].status != 'pass'){ doc.rect(200, initialYAxis+(0 * 25), 300, 25).fillAndStroke("#990000", "black"); }else{ doc.rect(200, initialYAxis+(0 * 25), 300, 25).fillAndStroke("#669966", "black"); } doc.fontSize(9).fillColor('black').text("Status", 105, 150 + (0 * 25) + 5); doc.fontSize(9).fillColor('black').text(tests[j].status, 205, 150 + (0 * 25) + 5); doc.rect(100, initialYAxis+(1 * 25), 100, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(200, initialYAxis+(1 * 25), 300, 25).fillAndStroke("white", "black"); doc.fontSize(9).fillColor('black').text("Start Time", 105, 150 + (1 * 25) + 5); doc.fontSize(9).fillColor('black').text(tests[j].start_date+" ms", 205, 150 + (1 * 25) + 5); doc.rect(100, initialYAxis+(2 * 25), 100, 25).fillAndStroke("#F0F0F0", "black"); doc.rect(200, initialYAxis+(2 * 25), 300, 25).fillAndStroke("white", "black"); doc.fontSize(9).fillColor('black').text("Duration", 105, 150 + (2 * 25) + 5); doc.fontSize(9).fillColor('black').text(batam_util.durationToStr(tests[j].duration.value), 205, 150 + (2 * 25) + 5); doc.moveDown(); doc.fontSize(12).fillColor('black').text("Logs:", 65, 250); doc.fontSize(8).text(tests[j].log == null ? '' : tests[j].log); } } } //Finish table of content doc.switchToPage(1); doc.moveDown(); doc.fillColor('black').fontSize(12).text('Summary',75, 150); doc.fillColor('black').fontSize(12).text('Page '+summaryPage, 450, 150); doc.fillColor('black').fontSize(12).text('Results By Functional Area',75, 170); doc.fillColor('black').fontSize(12).text('Page '+reportPage, 450, 170); doc.fillColor('black').fontSize(12).text('Results By Test',75, 190); doc.fillColor('black').fontSize(12).text('Page '+logPage, 450, 190); //Add page numbers var range = doc.bufferedPageRange(); for(var i = range.start; i < range.start + range.count; i++){ if(i != 0){ doc.switchToPage(i); doc.fontSize(8).text("Page "+(i + 1)+" of "+range.count, 470, 700); } } // end and display the document in the iframe to the right doc.end(); };
module.exports = function(danfe, args, callback) { if(typeof args === 'function') { callback = args; args = pdfDefaults; } args = merge(pdfDefaults, args); var emitente = danfe.getEmitente(), destinatario = danfe.getDestinatario(), transportador = danfe.getTransportador(), impostos = danfe.getImpostos(), volumes = danfe.getVolumes(), protocolo = danfe.getProtocolo(), itens = danfe.getItens(), fatura = danfe.getFatura(), alturaDoBlocoFaturaDuplicatas = 0, duplicatas = danfe.getDuplicatas(), pdf = new Pdf({ bufferPages: true, margin: 0, size: [ args.larguraDaPagina, args.alturaDaPagina ], info: { Author: args.autor, Title: args.titulo, Creator: args.criador, Producer: 'http://github.com/brasil-js/danfe' } }), pdfTemporario = new Pdf({ //TODO: Verificar se a criação deste pdf temporario // está causando problemas de performance margin: 0, size: [ args.larguraDaPagina, args.alturaDaPagina ] }), deveExibirQuadroDeCalculoDoIssqn = danfe.getValorTotalDosServicos() || impostos.getBaseDeCalculoDoIssqn() || impostos.getValorTotalDoIssqn(); if(args.stream) { pdf.pipe(args.stream); } pdf.registerFont('normal', timesNewRoman); pdf.registerFont('negrito', timesNewRomanNegrito); pdf.registerFont('italico', timesNewRomanItalico); pdf.registerFont('negrito-italico', timesNewRomanNegritoItalico); pdf.registerFont('codigoDeBarras', barcode.code128.font); pdfTemporario.registerFont('normal', timesNewRoman); ///////// LAYOUT var grossuraDaLinha = 0.5, margemTopo = 2.8, margemEsquerda = 3, margemDireita = 589.65, larguraDoFormulario = margemDireita - margemEsquerda; pdf.lineWidth(grossuraDaLinha); function linhaHorizontal(x1, x2, y, cor) { y = margemTopo + args.ajusteY + y; x1 = margemEsquerda + args.ajusteX + x1; x2 = margemDireita + args.ajusteX + x2; return pdf.moveTo(x1, y).lineTo(x2, y).stroke(); } function linhaHorizontalTracejada(x1, x2, y) { y = margemTopo + args.ajusteY + y; x1 = margemEsquerda + args.ajusteX + x1; x2 = margemDireita + args.ajusteX + x2; return pdf.moveTo(x1, y).lineTo(x2, y).dash(3, { space: 5 }).stroke(); } function linhaVertical(y1, y2, x, cor) { x = margemEsquerda + args.ajusteX + x; y1 = margemTopo + args.ajusteY + y1; y2 = margemTopo + args.ajusteY + y2; return pdf.moveTo(x, y1).lineTo(x, y2).stroke(); } function secao(string, x, y, largura, alinhamento, tamanho) { string = string || ''; x = margemEsquerda + args.ajusteX + x; y = margemTopo + args.ajusteY + y; pdf.font('negrito') .fillColor(args.corDaSecao) .fontSize(tamanho || args.tamanhoDaFonteDaSecao) .text(string.toUpperCase(), x, y, { width: largura, align: 'left' }); } function titulo(string, x, y, largura, alinhamento, tamanho) { string = typeof string !== 'undefined' && string !== null && string.toString() || ''; x = margemEsquerda + args.ajusteX + x; y = margemTopo + args.ajusteY + y; pdf.font('normal') .fillColor(args.corDoTitulo) .fontSize(tamanho || args.tamanhoDaFonteDoTitulo) .text(string.toUpperCase(), x, y, { width: largura, align: alinhamento || args.alinhamentoDoTitulo }); } function normal(string, x, y, largura, alinhamento, tamanho, _pdf) { string = string || ''; (_pdf || pdf).font('normal') .fillColor(args.corDoTitulo) .fontSize(tamanho || 8) .text(string, margemEsquerda + args.ajusteX + x, margemTopo + args.ajusteY + y, { width: largura, align: alinhamento || 'center', lineGap: -1.5 }); } function italico(string, x, y, largura, alinhamento, tamanho) { string = string || ''; pdf.font('italico') .fillColor(args.corDoTitulo) .fontSize(tamanho || 6) .text(string, margemEsquerda + args.ajusteX + x, margemTopo + args.ajusteY + y, { width: largura, align: alinhamento || 'center', lineGap: -1.5 }); } function negrito(string, x, y, largura, alinhamento, tamanho) { string = string || ''; pdf.font('negrito') .fillColor(args.corDoTitulo) .fontSize(tamanho || 6) .text(string, margemEsquerda + args.ajusteX + x, margemTopo + args.ajusteY + y, { width: largura, align: alinhamento || 'center', lineGap: -1.5 }); } function campo(string, x, y, largura, alinhamento, tamanho) { string = string || ''; pdf.font('negrito') .fillColor(args.corDoCampo) .fontSize(tamanho || args.tamanhoDaFonteDoCampo) .text(string, margemEsquerda + args.ajusteX + x, margemTopo + args.ajusteY + y, { width: largura, align: alinhamento || args.alinhamentoDoCampo }); } function desenharPagina() { if(args.ambiente !== 'producao') { pdf.font('normal') .fillColor(args.corDoTitulo) .fontSize(50) .fillOpacity(args.opacidadeDaHomologacao) .text('HOMOLOGAÇÃO', margemEsquerda + args.ajusteX + 0, margemTopo + args.ajusteY + 400 + args.ajusteYDaHomologacao, { width: larguraDoFormulario, align: 'center' }); pdf.font('normal') .fillColor(args.corDoTitulo) .fontSize(25) .fillOpacity(args.opacidadeDaHomologacao) .text('SEM VALOR FISCAL', margemEsquerda + args.ajusteX + 0, margemTopo + args.ajusteY + 450 + args.ajusteYDaHomologacao, { width: larguraDoFormulario, align: 'center' }); } //RECIBO linhaHorizontal(0, 0, 0); linhaHorizontal(0, -110.5, 28.3); linhaHorizontal(0, 0, 51.1); linhaVertical(0, 51.1, 0); linhaVertical(28.3, 51.1, 99.2); linhaVertical(0, 51.1, 476); linhaVertical(0, 51.1, 0); linhaVertical(0, 51.1, larguraDoFormulario); //PRIMEIRO BLOCO //QUADRADO DO TIPO (ENTRADA OU SAIDA) linhaHorizontal(317.4, -255, 96.4); linhaVertical(96.4, 116.2, 317.4); linhaHorizontal(317.4, -255, 116.2); linhaVertical(96.4, 116.2, 331.55); linhaHorizontal(0, 0, 59.55); linhaHorizontal(340.05, 0, 104.8); linhaHorizontal(340.05, 0, 127.4); linhaHorizontal(0, 0, 150.2); linhaHorizontal(0, 0, 170); linhaHorizontal(0, 0, 190); linhaVertical(59.55, 190, 0); linhaVertical(59.55, 150.2, 240.75); linhaVertical(59.55, 170, 340.05); linhaVertical(59.55, 190, larguraDoFormulario); linhaVertical(170, 190, 195.55); linhaVertical(170, 190, 391); //SEGUNDO BLOCO linhaHorizontal(0, 0, 201.2); linhaHorizontal(0, 0, 221); linhaHorizontal(0, 0, 241); linhaHorizontal(0, 0, 261); linhaVertical(201.2, 261, 0); linhaVertical(201.2, 221, 357.1); linhaVertical(221, 261, 274.9); linhaVertical(241, 261, 297.6); linhaVertical(221, 261, 396.75); linhaVertical(201.2, 261, 493.1); linhaVertical(201.2, 261, larguraDoFormulario); //TERCEIRO BLOCO linhaHorizontal(0, 0, 269); linhaHorizontal(0, 0, 289); linhaHorizontal(0, 0, 309); linhaVertical(269, 309, 0); linhaVertical(269, 309, 87.7); linhaVertical(269, 309, (87.7 * 2) + 0.3); linhaVertical(269, 309, (87.7 * 3) + 0.4); linhaVertical(269, 309, (87.7 * 4) + 0.4); linhaVertical(269, 309, (87.7 * 5) + 0.6); linhaVertical(269, 309, (87.7 * 5) + 51.8); linhaVertical(269, 309, larguraDoFormulario); //QUARTO BLOCO linhaHorizontal(0, 0, 320); linhaHorizontal(0, 0, 340); linhaHorizontal(0, 0, 360); linhaHorizontal(0, 0, 380); linhaVertical(320, 380, 0); linhaVertical(320, 340, 170); linhaVertical(320, 340, 346); linhaVertical(320, 360, 434); linhaVertical(320, 360, 456.65); linhaVertical(320, 380, 258); linhaVertical(360, 380, 59.6); linhaVertical(360, 380, 158.6); linhaVertical(360, 380, 357); linhaVertical(360, 380, 473.3); linhaVertical(320, 380, larguraDoFormulario); //QUINTO BLOCO - LISTA DE PRODUTOS var alturaInicialDoQuadroDeItens = 391, alturaInicialDoQuadroDeDuplicatas = alturaInicialDoQuadroDeItens, alturaDeLinhaDeDuplicata = 23, duplicatasPorLinha = 8, larguraDaDuplicata = larguraDoFormulario / duplicatasPorLinha, segundaLinhaDoQuadroDeItens, linhasDeDuplicatas = 0; if(fatura) { alturaDoBlocoFaturaDuplicatas += args.tamanhoDaFonteDoTitulo; alturaInicialDoQuadroDeDuplicatas += 6.5; } if(duplicatas.length) { linhasDeDuplicatas = Math.ceil(duplicatas.length / duplicatasPorLinha); alturaDoBlocoFaturaDuplicatas += (linhasDeDuplicatas * alturaDeLinhaDeDuplicata) + 10; } else { alturaDoBlocoFaturaDuplicatas += args.tamanhoDaFonteDoTitulo + 3; } duplicatas = gammautils.array.chop(duplicatas, duplicatasPorLinha); var margemDeCimaDaDuplicata = 2, margemEsquerdaDaDuplicata = 2, larguraDaDuplicataComMargem = larguraDaDuplicata - margemEsquerdaDaDuplicata - 1; duplicatas.forEach(function(linha, indiceDaLinha) { var x1, x2, y; linha.forEach(function(duplicata, indiceDaDuplicata) { x1 = indiceDaDuplicata * larguraDaDuplicata; x2 = x1 + larguraDaDuplicata - larguraDoFormulario; y = alturaInicialDoQuadroDeDuplicatas + (indiceDaLinha * alturaDeLinhaDeDuplicata); linhaHorizontal(x1, x2, y); linhaVertical(y, y + alturaDeLinhaDeDuplicata, x1); titulo('NÚM.', x1 + margemEsquerdaDaDuplicata, y + margemDeCimaDaDuplicata, larguraDaDuplicataComMargem); titulo(duplicata.getNumero(), x1 + margemEsquerdaDaDuplicata, y + margemDeCimaDaDuplicata, larguraDaDuplicataComMargem, 'right'); titulo('VENC.', x1 + margemEsquerdaDaDuplicata, y + margemDeCimaDaDuplicata + args.tamanhoDaFonteDoTitulo, larguraDaDuplicataComMargem, 'left'); titulo(duplicata.getVencimentoFormatado(), x1 + margemEsquerdaDaDuplicata, y + margemDeCimaDaDuplicata + args.tamanhoDaFonteDoTitulo, larguraDaDuplicataComMargem, 'right'); titulo('VALOR', x1 + margemEsquerdaDaDuplicata, y + margemDeCimaDaDuplicata + (2 * args.tamanhoDaFonteDoTitulo), larguraDaDuplicataComMargem, 'left'); titulo(duplicata.getValorFormatado(), x1 + margemEsquerdaDaDuplicata, y + margemDeCimaDaDuplicata + (2 * args.tamanhoDaFonteDoTitulo), larguraDaDuplicataComMargem, 'right'); }); linhaVertical(y, y + alturaDeLinhaDeDuplicata, x1 + larguraDaDuplicata); linhaHorizontal(0, x2, y + alturaDeLinhaDeDuplicata); }); // alturaInicialDoQuadroDeItens += alturaDoBlocoFaturaDuplicatas; segundaLinhaDoQuadroDeItens = alturaInicialDoQuadroDeItens + 14.2; linhaHorizontal(0, 0, alturaInicialDoQuadroDeItens); linhaHorizontal(0, 0, segundaLinhaDoQuadroDeItens); linhaHorizontal(0, 0, 751); linhaVertical(alturaInicialDoQuadroDeItens, 751, 0); linhaVertical(alturaInicialDoQuadroDeItens, 751, 53.8); linhaVertical(alturaInicialDoQuadroDeItens, 751, 235.3); linhaVertical(alturaInicialDoQuadroDeItens, 751, 269.3); linhaVertical(alturaInicialDoQuadroDeItens, 751, 292); linhaVertical(alturaInicialDoQuadroDeItens, 751, 314.5); linhaVertical(alturaInicialDoQuadroDeItens, 751, 331.6); linhaVertical(alturaInicialDoQuadroDeItens, 751, 371.2); linhaVertical(alturaInicialDoQuadroDeItens, 751, 405.4); linhaVertical(alturaInicialDoQuadroDeItens, 751, 439.3); linhaVertical(alturaInicialDoQuadroDeItens, 751, 473.2); linhaVertical(alturaInicialDoQuadroDeItens, 751, 507.2); linhaVertical(alturaInicialDoQuadroDeItens, 751, 535.6); linhaVertical(alturaInicialDoQuadroDeItens, 751, 555.4); linhaVertical(alturaInicialDoQuadroDeItens, 751, larguraDoFormulario); var alturaInicialDoSetimoBloco = 793.6; //SEXTO BLOCO if(deveExibirQuadroDeCalculoDoIssqn) { linhaHorizontal(0, 0, 762.2); linhaHorizontal(0, 0, 782.2); linhaVertical(762.2, 782.2, 0); linhaVertical(762.2, 782.2, 136.1); linhaVertical(762.2, 782.2, (136.1 * 2) - 0.1); linhaVertical(762.2, 782.2, (136.1 * 3) - 0.1); linhaVertical(762.2, 782.2, larguraDoFormulario); } else { alturaInicialDoSetimoBloco = 762.2; } // SÉTIMO BLOCO linhaHorizontal(0, 0, alturaInicialDoSetimoBloco); // x1, x2, y linhaHorizontal(0, 0, 821.8); linhaVertical(alturaInicialDoSetimoBloco, 821.8, 0); linhaVertical(alturaInicialDoSetimoBloco, 821.8, 388.25); linhaVertical(alturaInicialDoSetimoBloco, 821.8, larguraDoFormulario); // Deve ser a última linha pois não estou conseguindo // retirar o tracejado após utiliza-lo pela primeira vez linhaHorizontalTracejada(0, 0, 55.32); // MARGENS DA IMPRESSORA (ÚTIL PARA DEBUG) // linhaHorizontal(0, args.larguraDaPagina, 18, 'red'); // linhaHorizontal(0, args.larguraDaPagina, args.alturaDaPagina - 18, 'red'); // linhaVertical(0, args.alturaDaPagina, 18, 'red'); // linhaVertical(0, args.alturaDaPagina, args.larguraDaPagina - 22, 'red'); normal([ 'Recebemos de', emitente.getNome(), 'os produtos e/ou serviços constantes da nota', 'fiscal eletrônica indicada abaixo.', 'Emissão:', danfe.getDataDaEmissaoFormatada(), '- Valor Total:', danfe.getValorTotalDaNotaFormatado(), '- Destinatário:', destinatario.getNome(), '- Endereço:', destinatario.getEndereco().getPrimeiraLinha() ].join(' ').toUpperCase(), 1.5, 3, 472.5, 'justify', 6.9); titulo('DANFE', 266.5, 63.5, 197, 'left', 14); normal('NF-e', 476.6, 1.8, 110, 'center', 14); normal(danfe.getNumeroFormatado(), 476.6, 22, 110, 'center', 10); normal(danfe.getSerieFormatada(), 476.6, 31.5, 110, 'center', 10); italico('IDENTIFICAÇÃO DO EMITENTE', 1, 60, 238); var temLogotipo = emitente.getLogotipo(), identificacaoDoEmitenteY = temLogotipo ? 78 : 84, identificacaoDoEmitenteX = temLogotipo ? 67 : 1.5, identificacaoDoEmitenteLargura = temLogotipo ? 172 : 237,// identificacaoDoEmitenteFonte = temLogotipo ? 0 : 1.5; if(temLogotipo) { var caminhoDoLogotipo = emitente.getLogotipo(); pdf.image(caminhoDoLogotipo, margemEsquerda + args.ajusteX + 4.5, margemTopo + args.ajusteY + args.ajusteYDoLogotipo + 78, { fit: [60, 60] }); } negrito(emitente.getNome(), identificacaoDoEmitenteX, identificacaoDoEmitenteY + args.ajusteYDaIdentificacaoDoEmitente, identificacaoDoEmitenteLargura, 'center', 8 + identificacaoDoEmitenteFonte); if(emitente.getEndereco().getPrimeiraLinha()) { normal(emitente.getEndereco().getPrimeiraLinha(), identificacaoDoEmitenteX, pdf.y - margemTopo + 2, identificacaoDoEmitenteLargura, 'center', 6 + identificacaoDoEmitenteFonte); } if(emitente.getEndereco().getSegundaLinha()) { normal(emitente.getEndereco().getSegundaLinha(), identificacaoDoEmitenteX, pdf.y - margemTopo, identificacaoDoEmitenteLargura, 'center', 6 + identificacaoDoEmitenteFonte); } var jaAdicionouEspacamento = false; if(emitente.getTelefone()) { jaAdicionouEspacamento = true; normal('Telefone: ' + emitente.getTelefoneFormatado(), identificacaoDoEmitenteX, pdf.y - margemTopo + 2, identificacaoDoEmitenteLargura, 'center', 6 + identificacaoDoEmitenteFonte); } if(emitente.getEmail()) { normal('Email: ' + emitente.getEmail(), identificacaoDoEmitenteX, pdf.y - margemTopo + (jaAdicionouEspacamento ? 0 : 2), identificacaoDoEmitenteLargura, 'center', 6 + identificacaoDoEmitenteFonte); } normal('Documento Auxiliar da Nota Fiscal Eletrônica', 241.5, 77, 99.5); normal('0 - ENTRADA', 248, 100, 99.5, 'left'); normal('1 - SAÍDA', 248, 108.5, 99.5, 'left'); negrito(danfe.getTipoFormatado(), 317.5, 96.8, 14.5, 'center', 18); // CAMPO OPCIONAL 1 - FSDA var formularioDeSeguranca = danfe.getFormularioDeSeguranca(); if(protocolo.getFormatacao()) { normal('Consulta de autenticidade no portal nacional da NF-e', 340.5, 130, 244); normal('www.nfe.fazenda.gov.br/portal ou no site da Sefaz Autorizadora', 340.5, 138, 244); } else if(formularioDeSeguranca) { pdf.font('codigoDeBarras') .fontSize(18.5) .text(barcode.code128.encode(formularioDeSeguranca.getDadosDaNfe()), 341.5, 131.5, { align: 'center', width: 250 }); } var informacoesComplementares = [ danfe.getInformacoesComplementares() ]; if(formularioDeSeguranca) { informacoesComplementares.unshift([ 'DANFE EM CONTINGÊNCIA, ', 'IMPRESSO EM DECORRÊNCIA DE PROBLEMAS TÉCNICOS: ', formularioDeSeguranca.getJustificativa().toUpperCase(), ].join('')); } normal(informacoesComplementares.join(' - '), 1, alturaInicialDoSetimoBloco + 7.5, 386, 'justify', 6); normal(danfe.getNumeroFormatado(), 241.2, 119.5, 98.5, 'center', 10); normal(danfe.getSerieFormatada(), 241.2, 129.5, 98.5, 'center', 10); //RECIBO titulo('DATA DE RECEBIMENTO', 1.5, 29, 97); titulo('IDENTIFICAÇÃO E ASSINATURA DO RECEBEDOR', 100.5, 29, 374); var codigoDeBarrasCodificado = barcode.code128.encode(danfe.getChaveDeAcesso()); if(danfe.getChaveDeAcesso()) { pdf.font('codigoDeBarras') .fontSize(args.tamanhoDoCodigoDeBarras) .text(codigoDeBarrasCodificado, args.ajusteX + margemEsquerda + 339, args.ajusteY + margemTopo + 65, { align: 'center', width: 249 }); } //PRIMEIRO BLOCO titulo('CHAVE DE ACESSO', 341.5, 105.5, 244); campo(danfe.getChaveDeAcessoFormatada(), 341.5, 114, 244); if(protocolo.getFormatacao()) { titulo('PROTOCOLO DE AUTORIZAÇÃO DE USO', 341.5, 151, 244); campo(protocolo.getFormatacao(), 341.5, 158.4, 244); } else if(formularioDeSeguranca) { titulo('DADOS DA NFE', 341.5, 151, 244); campo(formularioDeSeguranca.getDadosDaNfeFormatado(), 341.5, 158.4, 244); } titulo('NATUREZA DA OPERAÇÃO', 1.5, 151, 338); campo(danfe.getNaturezaDaOperacao(), 1.5, 158.4, 338); titulo('INSCRIÇÃO ESTADUAL', 1.5, 171, 192.5); campo(emitente.getInscricaoEstadual(), 1.5, 178.4, 192.5); titulo('INSCRIÇÃO ESTADUAL DO SUBST. TRIBUT.', 197, 171, 192.5); campo(danfe.getInscricaoEstadualDoSubstitutoTributario(), 197, 178.4, 192.5); titulo('CNPJ', 392.5, 171, 192.5); campo(emitente.getRegistroNacionalFormatado(), 392.5, 178.4, 192.5); //SEGUNDO BLOCO secao('DESTINATÁRIO / REMETENTE', 1.5, 194); titulo('NOME / RAZÃO SOCIAL', 1.5, 202, 353.5); campo(destinatario.getNome(), 1.5, 210, 353.5, 'left'); titulo('CNPJ / CPF', 358, 202, 133.5); campo(destinatario.getRegistroNacionalFormatado(), 358, 210, 133.5); titulo('DATA DA EMISSÃO', 495, 202, 90); campo(danfe.getDataDaEmissaoFormatada(), 495, 210, 90); titulo('ENDEREÇO', 1.5, 222, 272); campo(destinatario.getEndereco().getPrimeiraLinha(), 1.5, 230, 272, 'left', args.tamanhoDaFonteDoCampo - 0.5); titulo('BAIRRO / DISTRITO', 276, 222, 119); campo(destinatario.getEndereco().getBairro(), 276, 230, 119); titulo('CEP', 398, 222, 93); campo(destinatario.getEndereco().getCepFormatado(), 398, 230, 93); titulo('DATA DA SAÍDA', 495, 222, 90); campo(danfe.getDataDaEntradaOuSaidaFormatada(), 495, 230, 90); titulo('MUNICÍPIO', 1.5, 242, 272); campo(destinatario.getEndereco().getMunicipio(), 1.5, 250, 272, 'left'); titulo('UF', 276, 242, 20); campo(destinatario.getEndereco().getUf(), 276, 250, 20); titulo('FONE / FAX', 299, 242, 96); campo(destinatario.getTelefoneFormatado(), 299, 250, 96); titulo('INSCRIÇÃO ESTADUAL', 398, 242, 93); campo(destinatario.getInscricaoEstadual(), 398, 250, 93); titulo('HORA DA SAÍDA', 495, 242, 90); campo(danfe.getHorarioDaEntradaOuSaida(), 495, 250, 90); //TERCEIRO BLOCO secao('CÁLCULO DO IMPOSTO', 1.5, 261.5); titulo('BASE DE CÁLCULO DO ICMS', 1.5, 270, 84); campo(impostos.getBaseDeCalculoDoIcmsFormatada(), 1.5, 278, 84, 'right'); titulo('VALOR DO ICMS', 89, 270, 84); campo(impostos.getValorDoIcmsFormatado(), 89, 278, 84, 'right'); titulo('BASE DE CÁLC. ICMS S.T.', 177, 270, 84); campo(impostos.getBaseDeCalculoDoIcmsStFormatada(), 177, 278, 84, 'right'); titulo('VALOR DO ICMS SUBST.', 265, 270, 84); campo(impostos.getValorDoIcmsStFormatado(), 265, 278, 84, 'right'); titulo('VALOR IMP. IMPORTAÇÃO', 353, 270, 84); campo(impostos.getValorDoImpostoDeImportacaoFormatado(), 353, 278, 84, 'right'); titulo('VALOR DO PIS', 441, 270, 47); campo(impostos.getValorDoPisFormatado(), 441, 278, 47, 'right'); titulo('VALOR TOTAL DOS PRODUTOS', 492, 270, 93); campo(danfe.getValorTotalDosProdutosFormatado(), 492, 278, 93, 'right'); titulo('VALOR DO FRETE', 1.5, 290, 84); campo(danfe.getValorDoFreteFormatado(), 1.5, 298, 84, 'right'); titulo('VALOR DO SEGURO', 89, 290, 84); campo(danfe.getValorDoSeguroFormatado(), 89, 298, 84, 'right'); titulo('DESCONTO', 177, 290, 84); campo(danfe.getDescontoFormatado(), 177, 298, 84, 'right'); titulo('OUTRAS DESPESAS', 265, 290, 84); campo(danfe.getOutrasDespesasFormatado(), 265, 298, 84, 'right'); titulo('VALOR TOTAL DO IPI', 353, 290, 84); campo(impostos.getValorTotalDoIpiFormatado(), 353, 298, 84, 'right'); titulo('VALOR DA COFINS', 440.5, 290.5, 47, null, args.tamanhoDaFonteDoTitulo - 1); campo(impostos.getValorDaCofinsFormatado(), 440.5, 298, 47, 'right'); titulo('VALOR TOTAL DA NOTA', 492, 290, 93); campo(danfe.getValorTotalDaNotaFormatado(false), 492, 298, 93, 'right'); //QUARTO BLOCO secao('TRANSPORTADOR / VOLUMES TRANSPORTADOS', 1.5, 312.5); titulo('NOME / RAZÃO SOCIAL', 1.5, 321, 166.5); campo(transportador.getNome(), 1.5, 329, 166.5, 'left'); titulo('FRETE POR CONTA', 171.5, 321, 85); campo(danfe.getModalidadeDoFreteFormatada(), 171.5, 329, 85); titulo('CÓDIGO ANTT', 259.5, 321, 84); campo(transportador.getCodigoAntt(), 259.5, 329, 84); titulo('PLACA DO VEÍCULO', 347.5, 321, 84); campo(transportador.getPlacaDoVeiculoFormatada(), 347.5, 329, 84); titulo('UF', 435.5, 321, 19.5); campo(transportador.getUfDaPlacaDoVeiculo(), 435.5, 329, 19.5); titulo('CNPJ / CPF', 458, 321, 126.5); campo(transportador.getRegistroNacionalFormatado(), 458, 329, 126.5); titulo('ENDEREÇO', 1.5, 341, 254); campo(transportador.getEndereco().getPrimeiraLinha(), 1.5, 349, 254, 'left', args.tamanhoDaFonteDoCampo - 0.5); titulo('MUNICÍPIO', 259.5, 341, 172); campo(transportador.getEndereco().getMunicipio(), 259.5, 349, 172); titulo('UF', 435.5, 341, 19.5); campo(transportador.getEndereco().getUf(), 435.5, 349, 19.5); titulo('INSCRIÇÃO ESTADUAL', 458, 341, 126.5); campo(transportador.getInscricaoEstadual(), 458, 349, 126.5); titulo('QUANTIDADE', 1.5, 361, 56.5); campo(volumes.getQuantidadeFormatada(), 1.5, 369, 56.5); titulo('ESPÉCIE', 60.8, 361, 96); campo(volumes.getEspecie(), 60.8, 369, 96); titulo('MARCA', 160, 361, 96); campo(volumes.getMarca(), 160, 369, 96); titulo('NUMERAÇÃO', 259.5, 361, 96); campo(volumes.getNumeracao(), 259.5, 369, 96); titulo('PESO BRUTO', 358.5, 361, 112.5); campo(volumes.getPesoBruto(), 358.5, 369, 112.5); titulo('PESO LÍQUIDO', 474.5, 361, 110.5); campo(volumes.getPesoLiquido(), 474.5, 369, 110.5); var alturaDaSecaoDosItens = 383, alturaDosTitulosDosItens; if(fatura || duplicatas.length) { secao('FATURA / DUPLICATAS', 1.5, 383); alturaDaSecaoDosItens += alturaDoBlocoFaturaDuplicatas; } if(fatura) { var dadosDaFatura = []; if(fatura.getNumero()) { dadosDaFatura.push('NÚMERO: ' + fatura.getNumero()); } if(fatura.getNumero()) { dadosDaFatura.push('VALOR ORIGINAL: ' + fatura.getValorOriginalFormatado()); } if(fatura.getNumero()) { dadosDaFatura.push('VALOR DO DESCONTO: ' + fatura.getValorDoDescontoFormatado()); } if(fatura.getNumero()) { dadosDaFatura.push('VALOR LÍQUIDO: ' + fatura.getValorLiquidoFormatado()); } if(fatura.getFormaDePagamento()) { dadosDaFatura.push('PAGAMENTO: ' + fatura.getFormaDePagamento()); } dadosDaFatura = dadosDaFatura.join(' - '); if(dadosDaFatura) { negrito(dadosDaFatura, 1.5, 390, larguraDoFormulario, 'left'); } } alturaDosTitulosDosItens = alturaDaSecaoDosItens + 12; // QUINTO BLOCO - LISTA DE PRODUTOS secao('DADOS DOS PRODUTOS / SERVIÇOS', 1.5, alturaDaSecaoDosItens); titulo('CÓDIGO', 1.5, alturaDosTitulosDosItens, 50.5, args.alinhamentoDoTituloDaTabela); titulo('DESCRIÇÃO DO PRODUTO / SERVIÇO', 55, alturaDosTitulosDosItens, 179, args.alinhamentoDoTituloDaTabela); titulo('NCM/SH', 236.5, alturaDosTitulosDosItens, 31.5, args.alinhamentoDoTituloDaTabela); titulo('O/CST', 270.5, alturaDosTitulosDosItens, 20, args.alinhamentoDoTituloDaTabela); titulo('CFOP', 293.5, alturaDosTitulosDosItens, 19.5, args.alinhamentoDoTituloDaTabela); titulo('UN.', 316, alturaDosTitulosDosItens, 14.5, args.alinhamentoDoTituloDaTabela); titulo('QUANT.', 333, alturaDosTitulosDosItens, 37, args.alinhamentoDoTituloDaTabela); titulo('VALOR UNIT.', 373, alturaDosTitulosDosItens - 4, 31.5, args.alinhamentoDoTituloDaTabela); titulo('VALOR TOTAL', 407.5, alturaDosTitulosDosItens - 4, 31.5, args.alinhamentoDoTituloDaTabela); titulo('B. CÁLC. ICMS', 441.5, alturaDosTitulosDosItens - 4, 31.5, args.alinhamentoDoTituloDaTabela); titulo('VALOR ICMS', 475, alturaDosTitulosDosItens - 4, 31.5, args.alinhamentoDoTituloDaTabela); titulo('VALOR IPI', 508, alturaDosTitulosDosItens - 4, 28, args.alinhamentoDoTituloDaTabela); titulo('ALÍQ. ICMS', 532, alturaDosTitulosDosItens - 4, 28, args.alinhamentoDoTituloDaTabela); titulo('ALÍQ. IPI', 557, alturaDosTitulosDosItens, 28, args.alinhamentoDoTituloDaTabela); // SEXTO BLOCO if(deveExibirQuadroDeCalculoDoIssqn) { secao('CÁLCULO DO ISSQN', 1.5, 754.5); titulo('INSCRIÇÃO MUNICIPAL', 1.5, 763, 132.5); campo(emitente.getInscricaoMunicipal(), 1.5, 771, 132.5, 'left'); titulo('VALOR TOTAL DOS SERVIÇOS', 137.5, 763, 132.5); campo(danfe.getValorTotalDosServicosFormatado(), 137.5, 771, 132.5, 'right'); titulo('BASE DE CÁLCULO DO ISSQN', 273.5, 763, 132.5); campo(impostos.getBaseDeCalculoDoIssqnFormatada(), 273.5, 771, 132.5, 'right'); titulo('VALOR TOTAL DO ISSQN', 409.5, 763, 175.5); campo(impostos.getValorTotalDoIssqnFormatado(), 409.5, 771, 175.5, 'right'); } var alturaDaSecaoDoSetimoBloco = 786, alturaDosTitulosDoSetimoBloco; if(!deveExibirQuadroDeCalculoDoIssqn) { alturaDaSecaoDoSetimoBloco = 754; } alturaDosTitulosDoSetimoBloco = alturaDaSecaoDoSetimoBloco + 9; // SÉTIMO BLOCO secao('DADOS ADICIONAIS', 1.5, alturaDaSecaoDoSetimoBloco); titulo('INFORMAÇÕES COMPLEMENTARES', 1.5, alturaDosTitulosDoSetimoBloco, 385); titulo('RESERVADO AO FISCO', 390, alturaDosTitulosDoSetimoBloco, 195); if(args.creditos) { italico(args.creditos, 1.5, 827, larguraDoFormulario); } } desenharPagina(); var numeroDePaginas = 1, yInicialDosItens = 406 + alturaDoBlocoFaturaDuplicatas, yDoItemAtual = yInicialDosItens, alturaAtual = 0; itens.forEach(function(item) { function renderizarLinha(pdf) { normal(item.getCodigo(), 1.5, yDoItemAtual, 51, 'center', args.tamanhoDaFonteDosItens, pdf); var maiorY = pdf.y; var descricao = item.getDescricao(); if(item.getInformacoesAdicionais()) { descricao += '\n' + item.getInformacoesAdicionais(); } normal(descricao, 55.5, yDoItemAtual, 178, 'justify', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getNcmSh(), 235.5, yDoItemAtual, 32.5, 'center', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getOCst(), 270, yDoItemAtual, 21, 'center', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getCfop(), 293.5, yDoItemAtual, 21, 'center', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getUnidade(), 315, yDoItemAtual, 16.5, 'center', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getQuantidadeFormatada(), 332.5, yDoItemAtual, 37.5, 'right', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getValorUnitarioFormatado(), 372, yDoItemAtual, 32.5, 'right', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getValorTotalFormatado(), 407, yDoItemAtual, 31, 'right', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getBaseDeCalculoDoIcmsFormatada(), 440, yDoItemAtual, 32.5, 'right', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getBaseDeCalculoDoIcmsFormatada(), 440, yDoItemAtual, 32.5, 'right', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getValorDoIcmsFormatado(), 474.5, yDoItemAtual, 32, 'right', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getValorDoIpiFormatado(), 508.5, yDoItemAtual, 26, 'right', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getAliquotaDoIcmsFormatada(), 536, yDoItemAtual + 0.65, 19, 'center', args.tamanhoDaFonteDosItens - 1, pdf); maiorY = Math.max(maiorY, pdf.y); normal(item.getAliquotaDoIpiFormatada(), 556.5, yDoItemAtual, 29, 'center', args.tamanhoDaFonteDosItens, pdf); maiorY = Math.max(maiorY, pdf.y); if(args.separadorDeItens) { linhaHorizontalTracejada(0, 0, maiorY); } return maiorY + (args.separadorDeItens ? 2 : 0); } var altura = renderizarLinha(pdfTemporario) - yDoItemAtual; if(alturaAtual + altura > (751 - yInicialDosItens)) { numeroDePaginas += 1; pdf.addPage(); yDoItemAtual = yInicialDosItens; alturaAtual = 0; desenharPagina(); } renderizarLinha(pdf); alturaAtual += altura; yDoItemAtual = yDoItemAtual + altura; }); var paginas = pdf.bufferedPageRange(); for(var i = paginas.start; i < paginas.start + paginas.count; i++) { pdf.switchToPage(i); italico('FOLHA ' + (i + 1) + '/' + numeroDePaginas, 241.2, 141.2, 98.5, 'center', 8); } pdf.flushPages(); pdf.end(); callback(null, pdf); };
lwip.open(Logo, function(err, image) { if (!err) { var ratio = 1; if (image.width() > widthLogo) ratio = widthLogo / image.width(); heightLogo = image.height() * ratio; } // else no logo or not readable // ----------------------------------------------------------------------------- // START var docinfo = { Producer: "PDFKit", Creator: param.ownerObj.ownerClean + " " + param.ownerObj.companyLegal, CreationDate: new Date(), Title: (param.quotationObj.quotationType == -1 ? "Devis n° " : "Facture n° ") + param.quotationObj.quotationRef, Author: param.ownerObj.username, Subject: (param.quotationObj.quotationType == -1 ? "Devis" : "Facture"), Keywords: "Devis,Facture," + param.ownerObj.ownerClean, ModDate: new Date() }; var thedoc = new pdf( { bufferPages: true, margin: margin, size: "A4", layout: "portrait", info: docinfo }); addTheHeader(thedoc, param); // ----------------------------------------------------------------------------- // MAIN PART addHeaderTable(thedoc, param); addContentTable(thedoc, param); // can we add Tables on the current page ? if ((getHTotalTable() + startTTC >= maxA4Y - margin - 6 * bigSize) || (getHPaymentTable(param) + startTTC >= maxA4Y - margin - 6 * bigSize)) { // NO console.log("New Page because of total tables"); // 1 finish last page addTheFooter(thedoc, param); // 2 start new page thedoc.addPage( { margin: margin, size: "A4", layout: "portrait" } ); range = thedoc.bufferedPageRange(); thedoc.switchToPage(range.start + range.count - 1); // go to the last page addTheHeader(thedoc, param); startTTC = startTab + normalSize * 2.5; } addTotalTable(thedoc, param); addPaymentTable(thedoc, param); addTheFooter(thedoc, param); range = thedoc.bufferedPageRange(); console.log("RANGE = " + util.inspect(range, false, null)); // ----------------------------------------------------------------------------- // FOOTER for(var np = range.start; np < range.start + range.count; np++) { thedoc.switchToPage(np); thedoc.font(normal).fontSize(normalSize).text("Page " + (np + 1) + " / " + range.count, maxA4X - 200 - margin, headerSecondLineY + betweenHeaderTableY, { width: 200, align: 'right' }); } // FINISH thedoc.flushPages() thedoc.end(); var docName = "/doc/" + param.quotationObj.quotationRef + "_" + param.quotationObj.quotationVersion + "_" + (new Date().getTime()) + ".pdf"; thedoc.pipe(fs.createWriteStream("./client" + docName)); self.insertUpdate(db, { quotationId: param.quotationId, docURL: docName }, function(err, ret) { if (ret.msg == "ok") { if (already >= 0) { // delete the old one self.delById(db, { docId: param.quotationObj.quotationDocList[already].docId }, function (err, ret) {} ); fs.unlink("./client" + param.quotationObj.quotationDocList[already].docURL); } var generatedDoc = {}; lodash.assign(generatedDoc, { quotationId: param.quotationId, quotationRef: param.quotationObj.quotationRef, quotationVersion: param.quotationObj.quotationVersion, quotationCreationDt: (new Date(param.quotationObj.quotationCreationDt)).format("DD-MM-YYYY"), quotationUpdateDt: (new Date(param.quotationObj.quotationUpdateDt)).format("DD-MM-YYYY HH:mm"), quotationEndValidityDt: param.quotationObj.quotationEndValidityDt ? (new Date(param.quotationObj.quotaitonEndValidityDt)).format("DD-MM-YYYY") : null, docId: ret.docId, docURL: docName } ); callback(null, generatedDoc); } else callback(null, generatedDoc); }); });