// import { PDFDocument } from "pdf-lib"; var n_pages = 0; var ha4 = 1123; var wa4 = 794; var border = 75; // page border / margins var margin = 50; // drawing margins var slabel = margin - 20; // spacing for dimension labels - ~ 10 < margin var hline = 25; var canvases = [document.getElementById("canvas_1")]; var ctxs = [canvases[0].getContext("2d")]; var myfont = 'arial'; // ToDo // var url_logo = 'https://github.com/Teddy-1024/Neural_Network/blob/master/Logo.png'; // direct html execution var url_logo = './Logo.png'; // positioning var h_my_b = 180; var h_issue = 325; var h_bank = 420; var h_billtosite = 560; var h_tablehead = 800; var h_row_max = 1050; // update this !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! var max_rows = round_down((h_row_max - h_tablehead) / hline); // table columns var w_tc1 = 120; var w_tc2 = 420; var w_tc3 = 520; var w_tc4 = 620; // file storage let fnm; // = namefile(); // // console.log(fnm); // document.getElementById('filename').value = fnm; process_localstorage(); Storage.prototype.setObj = function(key, obj) { return this.setItem(key, JSON.stringify(obj)) } Storage.prototype.getObj = function(key) { return JSON.parse(this.getItem(key)) } function my_LS_get_obj(key) { return JSON.parse(localStorage.getItem(key)); } // Template page layout function plot_page_layout(page_n, form_type) { // let h0 = (page_n - 1) * ha4; let i = page_n - 1; // canvas elements ctxs[i].beginPath(); ctxs[i].font = '20px ' + myfont; ctxs[i].fillText(form_type, border, 100); // ctxs[i].fillText('ESTIMATE', border, 100); ctxs[i].font = 'bold 12px ' + myfont; ctxs[i].fillText('BANK NAME:', border, h_bank); ctxs[i].fillText('ACCOUNT NAME:', border, h_bank + hline); ctxs[i].fillText('ACCOUNT NUMBER:', border, h_bank + hline * 2); ctxs[i].fillText('SORT CODE:', border, h_bank + hline * 3); ctxs[i].font = 'bold 12px ' + myfont; ctxs[i].fillText('ISSUE DATE:', wa4 / 2 + margin, h_issue); ctxs[i].fillText('DUE DATE:', wa4 / 2 + margin, h_issue + hline); ctxs[i].fillText('REFERENCE:', wa4 / 2 + margin, h_issue + hline * 2); ctxs[i].font = 'bold 12px ' + myfont; ctxs[i].fillText('BILL TO:', border, h_billtosite); ctxs[i].fillText('SITE / LOCATION:', wa4 / 2 + margin, h_billtosite); ctxs[i].stroke(); } function plot_page_interpersonal(page_n, date_due, my_ref) { // let h0 = (page_n - 1) * ha4; let i = page_n - 1; ctxs[i].font = '14px ' + myfont; ctxs[i].fillText(localStorage.my_b_name, border, h_my_b ); ctxs[i].font = '12px ' + myfont; ctxs[i].fillText(localStorage.my_b_address1, border, h_my_b+hline*1); ctxs[i].fillText(localStorage.my_b_address2, border, h_my_b+hline*2); ctxs[i].fillText(localStorage.my_b_address3, border, h_my_b+hline*3); ctxs[i].fillText(localStorage.my_b_address4, border, h_my_b+hline*4); ctxs[i].fillText(localStorage.my_b_address5, border, h_my_b+hline*5); ctxs[i].fillText(localStorage.my_b_email, border, h_my_b+hline*6); ctxs[i].fillText(localStorage.my_b_number, border, h_my_b+hline*7); // logo var img = new Image(); img.crossOrigin = "anonymous"; CORS_ALLOW_ALL_ORIGINS = true; img.style.border = 'none'; img.src = url_logo; // "https://raw.githubusercontent.com/Teddy-1024/Neural_Network/master/Deane_logo.png"; sz_img = 200; img.onload = function() { ctxs[i].drawImage(img, wa4 - border * 3 / 2 -sz_img, border, sz_img, sz_img); // , 0, 0, 0, 0, border + 25, border + 2, sz_img, sz_img); ctxs[i].stroke(); } ctxs[i].font = '12px ' + myfont; ctxs[i].fillText(localStorage.bank_name, border + 150, h_bank); ctxs[i].fillText(localStorage.bank_AC_name, border + 150, h_bank + hline); ctxs[i].fillText(localStorage.bank_AC_no, border + 150, h_bank + hline * 2); ctxs[i].fillText(localStorage.bank_SC, border + 150, h_bank + hline * 3); ctxs[i].font = '12px ' + myfont; ctxs[i].fillText(localStorage.date, wa4 / 2 + margin + 120, h_issue); ctxs[i].fillText(date_due, wa4 / 2 + margin + 120, h_issue + hline); ctxs[i].fillText(my_ref, wa4 / 2 + margin + 120, h_issue + hline * 2); ctxs[i].font = '12px ' + myfont; ctxs[i].fillText(localStorage.to_b_name, border, h_billtosite+hline*1); ctxs[i].fillText(localStorage.to_b_address1, border, h_billtosite+hline*2); ctxs[i].fillText(localStorage.to_b_address2, border, h_billtosite+hline*3); ctxs[i].fillText(localStorage.to_b_address3, border, h_billtosite+hline*4); ctxs[i].fillText(localStorage.to_b_address4, border, h_billtosite+hline*5); ctxs[i].fillText(localStorage.to_b_address5, border, h_billtosite+hline*6); ctxs[i].fillText(localStorage.to_b_email, border, h_billtosite+hline*7); ctxs[i].fillText(localStorage.to_b_phone, border, h_billtosite+hline*8); ctxs[i].fillText(localStorage.client_contact, wa4/2 + margin, h_billtosite+hline*1); ctxs[i].fillText(localStorage.client_name, wa4/2 + margin, h_billtosite+hline*2); ctxs[i].fillText(localStorage.client_address1, wa4/2 + margin, h_billtosite+hline*3); ctxs[i].fillText(localStorage.client_address2, wa4/2 + margin, h_billtosite+hline*4); ctxs[i].fillText(localStorage.client_address3, wa4/2 + margin, h_billtosite+hline*5); ctxs[i].fillText(localStorage.client_address4, wa4/2 + margin, h_billtosite+hline*6); ctxs[i].stroke(); } function round_down(quotient) { let temp = quotient % 1; return quotient - temp; } function round_up(quotient) { let temp = quotient % 1; if (temp == 0) { return quotient; } return 1 + quotient - temp; } function plot_line_gs(description, quantity, rate, subtotal, h, page_i) { let i = page_i - 1; ctxs[i].font = '12px ' + myfont; ctxs[i].fillText(description, w_tc1, h); ctxs[i].fillText(quantity, w_tc2, h); ctxs[i].fillText(rate, w_tc3, h); ctxs[i].fillText(subtotal, w_tc4, h); } function plot_line_pp(description, date, value, h, page_i) { let i = page_i - 1; ctxs[i].font = '12px ' + myfont; ctxs[i].fillText(description, w_tc1, h); ctxs[i].fillText(date, (w_tc2 + w_tc3) / 2, h); ctxs[i].fillText(value, w_tc4, h); } function plot_table_headings_payplan(h, page_i) { let i = page_i - 1; let currency = localStorage.getItem('currency'); ctxs[i].font = 'bold 12px ' + myfont; ctxs[i].fillText('DESCRIPTION', w_tc1 + 20, h); ctxs[i].fillText('DATE', (w_tc2 + w_tc3 + 25) / 2, h); ctxs[i].fillText('VALUE [' + currency + ']', w_tc4 - 16, h); // latinum conversion rates // 500 .bars, 10,000 .strips, 1,000,000 .slips } function plot_table_headings_invest(ratedisc, h, page_i) { let i = page_i - 1; let currency = localStorage.getItem('currency'); ctxs[i].font = 'bold 12px ' + myfont; ctxs[i].fillText('DESCRIPTION', w_tc1 + 30, h); if (ratedisc[0] == 'Unit cost') { ctxs[i].fillText('QUANTITY', w_tc2 - 20, h); ctxs[i].fillText('UNIT COST [' + currency + ']', w_tc3 - 12, h); } else { ctxs[i].fillText(currency + ' / ' + ratedisc[0], w_tc3 - 12, h); ctxs[i].fillText('# ' + ratedisc[1], w_tc2 - 20, h); } ctxs[i].fillText('SUBTOTAL', w_tc4-10, h); } function plot_subtotal(tot, h, page_i) { let i = page_i - 1; ctxs[i].font = '12px ' + myfont; ctxs[i].fillText('£ ' + tot.toFixed(2), w_tc4 - 10, h); ctxs[i].font = 'bold 12px ' + myfont; ctxs[i].fillText('TOTAL:', w_tc4 - border - 10, h); } function plot_invest(form_type, do_goods, rows_g, n_goods, do_services, rows_s, n_services, n_subs, ratedisc, date_due, my_ref) { let txt_base_border = 0.5 * hline; let min_table_delta = 2 * hline + txt_base_border; let max_table_height = 1000; // // ctx.beginPath(); // ctx.font = '20px ' + myfont; // ctx.fillText(form_type, border, 100); let n_plotted = 0; let page_i = 0; // let h0 = (page_i - 1) * ha4; let h1 = 0; // ctx.font = '12px ' + myfont; let subtotal; // goods if (do_goods) { subtotal = 0; for (let row_i = 0; row_i < n_goods; row_i++) { h1 = h_tablehead + (row_i - n_plotted) * hline; if (row_i % max_rows == 0) { page_i++; n_plotted = row_i - 1; // h0 = (page_i - 1) * ha4; // plot new page // ctxs[page_i - 1].font = '20px ' + myfont; // ctxs[page_i - 1].fillText(form_type, border, 100); ctxs[page_i - 1].font = '12px ' + myfont; plot_page_layout(page_i, form_type); plot_page_interpersonal(page_i, date_due, my_ref); plot_table_headings_invest(['Unit cost'], h_tablehead, page_i); } h1 = h_tablehead + (row_i - n_plotted) * hline; plot_line_gs(rows_g[row_i][0], rows_g[row_i][1], rows_g[row_i][2], rows_g[row_i][3], h1, page_i); subtotal += Number( rows_g[row_i][3]); } // output subtotal h1 += hline; plot_subtotal(subtotal, h1, page_i); } // services if (do_services) { if (!do_goods) { page_i++; h1 = h_tablehead; ctxs[0].font = '12px ' + myfont; plot_page_layout(page_i, form_type); plot_page_interpersonal(page_i, date_due, my_ref); } for (let i = 0; i < n_services; i++) { subtotal = 0; if (max_table_height - min_table_delta < h1) { // new page, reset start height page_i++; // h0 = (page_i - 1) * ha4; h1 = h_tablehead; // plot new page // ctxs[page_i - 1].font = '20px ' + myfont; // ctxs[page_i - 1].fillText(form_type, border, 100); ctxs[page_i - 1].font = '12px ' + myfont; plot_page_layout(page_i, form_type); plot_page_interpersonal(page_i, date_due, my_ref); } else { h1 += hline * 1.2; } // plot table headings plot_table_headings_invest(ratedisc[i], h1, page_i); // plot rows for (let j = 0; j < n_subs[i]; j++) { h1 += hline; if (max_table_height - txt_base_border < h1) { // new page, reset start height page_i++; // h0 = (page_i - 1) * ha4; h1 = h_tablehead; // plot new page plot_page_layout(page_i, form_type); plot_page_interpersonal(page_i, date_due, my_ref); plot_table_headings_invest(ratedisc[i], h1, page_i); h1 += hline; } // plot row plot_line_gs(rows_s[i][j][0], rows_s[i][j][1], rows_s[i][j][2], rows_s[i][j][3], h1, page_i); subtotal += Number(rows_s[i][j][3]); } // output subtotal h1 += hline; plot_subtotal(subtotal, h1, page_i); } } if (page_i < n_pages) { let canvas_container = document.getElementById('parent_canvases'); for (let i = page_i + 1; i <= n_pages; i++) { canvas_container.removeChild(document.getElementById('canvas_' + i)); } n_pages = page_i; } } function plot_payplan(rows_p, n_pay, my_ref) { let txt_base_border = 0.5 * hline; let min_table_delta = 1 * hline + txt_base_border; let max_table_height = 1000; // ctx.beginPath(); // ctx.font = '20px ' + myfont; // ctx.fillText('PAYMENT-PLAN', border, 100); let n_plotted = 0; let page_i = 0; // let h0 = (page_i - 1) * ha4; let h1; // ctx.font = '12px ' + myfont; let subtotal = 0; // goods if (n_pay >= 1) { for (let row_i = 0; row_i < n_pay; row_i++) { h1 = h_tablehead + (row_i - n_plotted) * hline; if (row_i % max_rows == 0) { page_i++; // h0 = (page_i - 1) * ha4; n_plotted = row_i - 1; // plot new page plot_page_layout(page_i, 'PAYMENT-PLAN'); plot_page_interpersonal(page_i, rows_p[n_pay - 1][1], my_ref); plot_table_headings_payplan(h_tablehead, page_i); } h1 = h_tablehead + (row_i - n_plotted) * hline; plot_line_pp(rows_p[row_i][0], rows_p[row_i][1], rows_p[row_i][2], h1, page_i); subtotal += Number(rows_p[row_i][2]); } // output subtotal h1 += hline; plot_subtotal(subtotal, h1, page_i); } // ctx.stroke(); } // borders // ctx.strokeStyle = "blue"; // ctx.fillRect(margin, margin, wa4 - 2 * (border - margin - 5), border - margin - 5); // ctx.fillRect(margin, ha4 - margin, wa4 - 2 * (border - margin - 5), border - margin - 5); // ctx.stroke(); function create_canvases(quantity) { if (quantity > 1) { let div_parent = document.getElementById('parent_canvases'); for (let i = 2; i <= quantity; i++) { let new_canvas = document.createElement('canvas'); new_canvas.id = 'canvas_' + i.toString(); new_canvas.width = wa4; new_canvas.height = ha4; new_canvas.style.border = 'none'; new_canvas.style.margin = 'auto'; new_canvas.innerText = 'Your browser does not support the HTML5 canvas tag.'; div_parent.appendChild(new_canvas); canvases.push(new_canvas); ctxs.push(canvases[i - 1].getContext('2d')); } } } function namefile(form_type, my_ref, date_due = '') { let svname; switch (form_type) { case 'PAYMENT-PLAN': svname = 'Payment-Plan_' + my_ref + '_' + date_due; break; default: // let endweek = Number(localStorage.week1) + Number(localStorage.nweeks - 1); // svname = 'Invoice_Contechs_00-J55589_' + localStorage.date.substr(2, 2) + '_wks_'; // svname = svname.concat(localStorage.week1); // svname = svname.concat('-'); // svname = svname.concat(endweek); // Chassis Business Process Analyst 00-J55589 // svname = form_type.charAt(0) + form_type.substring(1, form_type.length).toLowerCase() + '_Contechs_00-J55589_' + my_ref; // RADs Software Engineer 00-J56557 // svname = form_type.charAt(0) + form_type.substring(1, form_type.length).toLowerCase() + '_Contechs_00-J56557_' + my_ref; svname = "file_reference" break; } document.getElementById('filename').value = svname; return svname; } function imgclick(canvas_i) { // download file! const { jsPDF } = window.jspdf; const pdf = new jsPDF(); const imgData = canvases[canvas_i].toDataURL("image/png", 1.0); pdf.addImage(imgData, 'PNG', 0, 0); pdf.save(document.getElementById('filename').value + '_' + (canvas_i + 1).toString()); // mailsend(pdf); } function download_pdfs(download_type = 'separate') { // download type = 'together' (default) or 'separate' // switch (download_type) { // case 'separate': for (let i = 0; i < n_pages; i++) { imgclick(i); } // break; // default: // const { // jsPDF // } = window.jspdf; // const doc = new jsPDF(); // const arrayBuffer = doc.output('arraybuffer'); // let pdf_list = []; // for (let canvas_i = 0; canvas_i < n_pages; canvas_i++) { // const pdf = new jsPDF(); // const imgData = canvases[canvas_i].toDataURL("image/png", 1.0); // pdf.addImage(imgData, 'PNG', 0, 0); // } // let merged_pdf = mergePdfs(pdf_list); // merged_pdf.save(document.getElementById('filename').value); // break; // } } // async function mergePdfs(pdfsToMerges) { // : ArrayBuffer[] // const mergedPdf = await PDFDocument.create(); // const actions = pdfsToMerges.map(async pdfBuffer => { // const pdf = await PDFDocument.load(pdfBuffer); // const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices()); // copiedPages.forEach((page) => { // // console.log('page', page.getWidth(), page.getHeight()); // // page.setWidth(210); // mergedPdf.addPage(page); // }); // }); // await Promise.all(actions); // const mergedPdfFile = await mergedPdf.save(); // return mergedPdfFile; // } function gen_inv_ID(companycode, week1, weekn, date) { let year = date.substr(2, 2);// date.getFullYear(); let name = year + "_wks_" + week1 + "-" + weekn; return name; } function gen_date_due(date0) { let date_0 = new Date(date0); let y0 = date_0.getFullYear(); let m0 = date_0.getMonth(); // let d0 = date0.getDate(); // let month = Number(date.substr(5, 2)); // let year = Number(date.substr(0, 4)); let date_1 = new Date(y0, m0 + 2, 1); // if (month >= 11) { // year = year + 1; // month = month - 10; // } else { // month = month + 2; // } let n_working_days = 1; let n_days_total = 4; let date_temp = date_1; for (let i = 1; i < 6; i++) { date_temp.setDate(date_temp.getDate() + 1); let billday = date_temp.getDay(); if (!(billday == 0 || billday == 6)) { n_working_days++; } if (n_working_days == n_days_total) { break; } } let date_2 = date_temp; return date2str(date_2); // for (let i = 0; i < 6; i++) { // billday = i + 1; // let tempbilldate = new Date(year.toString() + '-' + month.toString().padStart(2, '0') + '-' + billday.toString().padStart(2, '0')); // let tempbillday = tempbilldate.getDay(); // {Sunday - Saturday = 0 - 6} // if (!(tempbillday == 0 || tempbillday == 6)) { // n_working_days++; // } // if (n_working_days == n_days_total) { // break; // } // } // return year.toString() + '-' + month.toString().padStart(2, '0') + '-' + billday.toString().padStart(2, '0'); } function date2str(date_in) { return date_in.getFullYear().toString() + '-' + (date_in.getMonth() + 1).toString().padStart(2, '0') + '-' + date_in.getDate().toString().padStart(2, '0'); } function process_localstorage() { // find form type and get rows let form_type = localStorage.getItem('form_type'); console.log('form type = ' + form_type); switch (form_type) { case 'PAYMENT-PLAN': let n_pay = Number(localStorage.getItem('payments_n')); let paytype = localStorage.getItem('paytype'); let values = []; let dates = []; let rows_p = []; switch (paytype) { case 'linear': values.push(localStorage.getItem('pay_value_unit')); if (n_pay > 1) { for (let i = 1; i < n_pay; i++) { values.push(values[0]); } } break; case 'multiplier': let value_0 = Number(localStorage.getItem('pay_value_unit')); let multipliers = my_LS_get_obj('multiplier'); if (n_pay > 1) { for (let i = 0; i < n_pay; i++) { values.push((value_0 * multipliers[i]).toString()); } } break; case 'random': let randoms = my_LS_get_obj('value'); if (n_pay > 1) { for (let i = 0; i < n_pay; i++) { values.push(randoms[i]); } } break; } let description = localStorage.getItem('description'); // let discretisation = localStorage.getItem('discretisation'); // let payscheme = localStorage.getItem('payscheme'); let dates_in = my_LS_get_obj('dates'); // let disc_quantity = Number(localStorage.getItem('disc_quantity')); for (let i = 0; i < n_pay; i++) { dates.push(date2str(new Date(dates_in[i]))); } for (let i = 0; i < n_pay; i++) { rows_p.push([description, dates[i], values[i]]); } n_pages = round_up(n_pay / max_rows) // canvas.height = ha4 * n_pages; fnm = namefile(form_type, localStorage.week1, dates[0]); create_canvases(n_pages); plot_payplan(rows_p, n_pay, localStorage.week1); break; default: // case 'INVOICE' || 'ESTIMATE': let inv_ref = gen_inv_ID(localStorage.to_b_code, localStorage.week1, String(Number(localStorage.week1) + Number(localStorage.subservice_quantities.substring(2, localStorage.subservice_quantities.substring(2).indexOf('"') + 2)) - 1), localStorage.date); let date_due = gen_date_due(localStorage.date); let rows_g = []; let nrows_g = 0; let goods_n = 0; let rows_s = []; // let n_services = 0; let services_n; let n_subs = []; // let durnrates = []; let do_goods = localStorage.getItem('bool_goods') == 'true'; if (do_goods) { goods_n = Number(localStorage.getItem('goods_n')); let mygoods_n = my_LS_get_obj('mygoods_n'); let mygoods_q = my_LS_get_obj('mygoods_q'); let mygoods_v = my_LS_get_obj('mygoods_v'); for (let i = 1; i <= goods_n; i++) { nrows_g++; rows_g.push([mygoods_n[i - 1], mygoods_q[i - 1], mygoods_v[i - 1], (Number(mygoods_v[i - 1]) * Number(mygoods_q[i - 1])).toFixed(2)]); } n_pages = round_up(goods_n / max_rows); } let do_services = localStorage.getItem('bool_services') == 'true'; let ratediscs; // let durndiscs; if (do_services) { // n_services = 1; services_n = Number(localStorage.getItem('services_n')); ratediscs = my_LS_get_obj('ratediscs'); // durndiscs = my_LS_get_obj('durndiscs'); let rates = my_LS_get_obj('rates'); // let durn_disc_qs = my_LS_get_obj('durn_disc_qs'); let description = my_LS_get_obj('descriptions'); let quantities = my_LS_get_obj('quantities'); let subservice_quantities = my_LS_get_obj('subservice_quantities'); for (let i = 1; i <= services_n; i++) { // let my_serve = -1; // for (let j = 0; j < n_subs[i - 1]; j++) { // if (durnrates[j][0] == durndiscs[i - 1] && durnrates[j][1] == ratediscs[i - 1]) { // my_serve = j; // break; // } // } // if (my_serve == -1) { // my_serve = n_services - 1; n_subs.push(0); // durnrates.push([durndiscs[i - 1], ratediscs[i - 1]]); rows_s.push([]); // n_services++; // } for (let j = 1; j <= Number(subservice_quantities[i - 1]); j++) { n_subs[i - 1]++; rows_s[i - 1].push([description[i - 1][j - 1], quantities[i - 1][j - 1], rates[i - 1], (Number(quantities[i - 1][j - 1]) * Number(rates[i - 1])).toFixed(2)]); } n_pages += round_up(n_subs[i - 1] / max_rows); } } // canvas.height = ha4 * n_pages; fnm = namefile(form_type, inv_ref); create_canvases(n_pages); plot_invest(form_type, do_goods, rows_g, goods_n, do_services, rows_s, services_n, n_subs, ratediscs, date_due, inv_ref); break; } }