/* © 2026 K2B NETWORK SOLUTIONS LLC. All rights reserved. Proprietary and confidential. Unauthorized copying, distribution, or use of this file, via any medium, is strictly prohibited. Original work product. */ /* eslint-disable */ // K2B DMS — check printing on blank security check stock (8.5" × 11"). // stock "top": check on top (3.5"), two stubs below (payee copy + file copy) // stock "3up": three checks per page (3.5" each) + 0.5" tear strip // Everything is placed in inches from the page corner with @page margin 0, so // it lands in the same spot on every printer set to 100% / Actual size. // MICR line (ANSI X9.100-160 / E-13B positions): characters on an exact 1/8" // pitch measured from the check's right edge (position 1 starts 5/16" in): // 1–12 amount (left blank — the bank encodes it) · 14 on-us ⑈ · // 15–32 account · 33 ⑆ · 34–42 routing · 43 ⑆ · 45+ aux on-us ⑈check#⑈ // The glyphs need an E-13B MICR font: one installed on the printing PC // (GnuMICR, "MICR Encoding", "MICR E13B", IDAutomation…) or one uploaded in // Check Setup. Font character map (the common one): A ⑆ transit, B ⑇ amount, // C ⑈ on-us, D ⑉ dash. const CKP_FONT_STACK = `"K2BMICR", "GnuMICR", "MICR Encoding", "MICR E13B", "MICR", "E13B", "IDAutomationMICR", "IDAutomationSMICR", "MICRE13B"`; const CKP_LOCAL_FONTS = ["GnuMICR", "MICR Encoding", "MICR E13B", "MICR", "E13B", "IDAutomationMICR", "IDAutomationSMICR", "MICRE13B"]; const ckpEsc = (s) => String(s == null ? "" : s).replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); const ckpMoney = (n) => (Number(n) || 0).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); /* ── amount in words: 1234.56 → "One Thousand Two Hundred Thirty-Four and 56/100" ── */ const CKP_ONES = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"]; const CKP_TENS = ["", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"]; const ckpUnder1000 = (n) => { const out = []; if (n >= 100) { out.push(CKP_ONES[Math.floor(n / 100)] + " Hundred"); n %= 100; } if (n >= 20) { out.push(CKP_TENS[Math.floor(n / 10)] + (n % 10 ? "-" + CKP_ONES[n % 10] : "")); } else if (n > 0) out.push(CKP_ONES[n]); return out.join(" "); }; const ckpWords = (amount) => { const cents = Math.round((Number(amount) || 0) * 100); let dollars = Math.floor(cents / 100); const c = cents % 100; if (dollars === 0) return `Zero and ${String(c).padStart(2, "0")}/100`; const parts = []; [[1e9, "Billion"], [1e6, "Million"], [1e3, "Thousand"], [1, ""]].forEach(([size, name]) => { if (dollars >= size) { const chunk = Math.floor(dollars / size); dollars %= size; parts.push(ckpUnder1000(chunk) + (name ? " " + name : "")); } }); return `${parts.join(" ")} and ${String(c).padStart(2, "0")}/100`; }; /* ── MICR line: [{pos, ch}] for the font (A/B/C/D symbols) ── */ const ckpMicrChars = (bank, num, opts) => { const routing = String(bank.routing || "").replace(/\D/g, ""); const account = String(bank.account || "").replace(/[^0-9-]/g, ""); const chk = String(num || "").replace(/\D/g, ""); const out = []; const putRight = (str, endPos) => { const s = String(str); for (let i = 0; i < s.length; i++) out.push({ pos: endPos + (s.length - 1 - i), ch: s[i] }); }; // transit field 33–43 if (routing) putRight("A" + routing + "A", 33); const acc = account.replace(/-/g, "D"); if ((bank.micrFormat || "business") === "personal") { // on-us: account ⑈ check# (ending at position 14) if (acc || chk) putRight(acc + "C" + (chk ? chk.padStart(4, "0") : ""), 14); } else { // on-us: account ⑈ at 14; auxiliary on-us ⑈check#⑈ ending at 45 if (acc) putRight(acc + "C", 14); if (chk) putRight("C" + chk.padStart(opts && opts.auxDigits || 6, "0") + "C", 45); } return out; }; const CKP_SYMBOL_FALLBACK = { A: "⑆", B: "⑇", C: "⑈", D: "⑉" }; /* ── one check face at (x0, y0) inches ── */ const ckpFace = (c, bank, company, x0, y0, opts) => { const o = opts || {}; const ox = x0 + (+bank.offsetX || 0), oy = y0 + (+bank.offsetY || 0); const at = (x, y, html, style) => `
${html}
`; const words = ckpWords(c.amount); const fill = "*".repeat(Math.max(3, 62 - words.length)); const date = c.date ? new Date(c.date) : new Date(); const dateStr = `${String(date.getMonth() + 1).padStart(2, "0")}/${String(date.getDate()).padStart(2, "0")}/${date.getFullYear()}`; const top = bank.stock === "3up" ? 0.18 : 0.30; // top-check stock has the "to verify authenticity" bar const addr = String(c.payeeAddr || "").split(/\r?\n/).map(s => s.trim()).filter(Boolean).slice(0, 3); let h = ""; h += at(0.40, top, `${ckpEsc(company.name)}
${ckpEsc(company.addr1)}
${ckpEsc(company.addr2)}${company.phone ? "
" + ckpEsc(company.phone) : ""}`, "font-size:8.5pt;line-height:1.25;width:3.3in"); h += at(3.75, top, `${ckpEsc(bank.bankName || "")}${bank.bankLine2 ? "
" + ckpEsc(bank.bankLine2) : ""}${bank.fractional ? "
" + ckpEsc(bank.fractional) : ""}`, "font-size:8pt;line-height:1.25;width:2.4in;text-align:center"); h += at(6.40, top, `${ckpEsc(c.num)}`, "width:1.75in;text-align:right"); h += at(6.00, top + 0.62, `DATE  ${dateStr}`, "width:2.15in;text-align:right;font-size:10.5pt"); h += at(0.40, top + 1.00, `PAY  ${ckpEsc(words)} ${fill}`, "width:6.6in;white-space:nowrap;overflow:hidden;font-size:10pt"); h += at(7.10, top + 1.00, `DOLLARS`, "width:1.0in;text-align:right"); h += at(0.40, top + 1.38, `TO THE
ORDER OF
`, "font-size:7pt;line-height:1.1"); h += at(1.10, top + 1.40, `${ckpEsc(c.payee)}${addr.map(l => "
" + ckpEsc(l)).join("")}`, "width:4.6in;line-height:1.3;font-size:9.5pt"); h += at(6.25, top + 1.32, `$${"*".repeat(Math.max(2, 11 - ckpMoney(c.amount).length))}${ckpMoney(c.amount)}`, "width:1.9in;text-align:right;font-size:12.5pt;border:1px solid #000;padding:3px 6px;box-sizing:border-box"); if (bank.voidAfterDays) h += at(6.25, top + 1.72, `VOID AFTER ${bank.voidAfterDays} DAYS`, "width:1.9in;text-align:right;font-size:6.5pt"); h += at(0.40, top + 2.38, `MEMO  ${ckpEsc(c.memo || (c.inv ? "Inv " + c.inv : ""))}`, "width:4.2in;font-size:9pt;white-space:nowrap;overflow:hidden"); if (bank.sigLine && bank.stock !== "3up") { const lines = bank.sigLines === 2 ? 2 : 1; for (let i = 0; i < lines; i++) h += at(5.05, top + 2.48 - (lines - 1 - i) * 0.42, `
${i === lines - 1 ? "AUTHORIZED SIGNATURE" : (bank.sigOver ? ckpEsc(bank.sigOver) : "AUTHORIZED SIGNATURE")}
`); } // MICR — bottom of the characters 0.25" above the check's bottom edge (inside the 5/8" clear band) const H = 3.5; const micrTop = oy + H - 0.25 - 0.19 + (+bank.micrOffsetY || 0); const rightEdge = ox + 8.5; ckpMicrChars(bank, c.num).forEach(({ pos, ch }) => { const left = rightEdge - 0.3125 - pos * 0.125; const glyph = o.fallback ? (CKP_SYMBOL_FALLBACK[ch] || ch) : ch; h += `
${ckpEsc(glyph)}
`; }); if (o.alignment) { h += `
`; h += `
`; } return h; }; /* ── stub (top-check stock) ── */ const ckpStub = (c, bank, company, y0, label) => { const at = (x, y, html, style) => `
${html}
`; const D = window.DMS || {}; const name = (a) => (D.acctName ? D.acctName(a) : "") || ""; const d = c.date ? new Date(c.date).toLocaleDateString("en-US") : ""; const rows = (c.lines && c.lines.length ? c.lines : [{ inv: c.inv || "", desc: c.memo || "", amount: c.amount }]) .map(l => `${ckpEsc(l.inv || "")}${ckpEsc(l.desc || "")}${ckpMoney(l.amount)}`).join(""); return at(0, 0.30, `
${ckpEsc(company.name)}${ckpEsc(label)}
Check # ${ckpEsc(c.num)}Date ${ckpEsc(d)}Payee ${ckpEsc(c.payee)}Amount $${ckpMoney(c.amount)}
${rows}
InvoiceDescriptionAmount
GL accountDebitCredit
${ckpEsc(c.acct)}${ckpEsc(name(c.acct))}${ckpMoney(c.amount)}
${ckpEsc(c.bankAcct || bank.glAcct)}${ckpEsc(name(c.bankAcct || bank.glAcct) || bank.label)}${ckpMoney(c.amount)}
`, "width:7.6in"); }; /* ── whole document ── */ const ckpDoc = (checks, opts) => { const o = opts || {}; const D = window.DMS || {}; const cfg = D.checkConfig ? D.checkConfig() : { accounts: [] }; // RC35 (brd): Check setup's company lines, else the store's check header, else its print name + address (K2BPrint.checkCompany) const company = window.K2BPrint ? window.K2BPrint.checkCompany(cfg) : { name: "", addr1: "", addr2: "", phone: "" }; // (ldg) a reprint uses the print data the server stored with the check (what the paper says: company lines, bank name / // city / fractional, stock and signature settings); the routing / account numbers and the printer offsets stay live settings const liveBank = (c) => (cfg.accounts || []).find(a => a.id === (c.bankId || o.bankId || cfg.defaultId)) || (cfg.accounts || [])[0] || {}; const bankOf = (c) => (c && c.printData && c.printData.bank) ? { ...liveBank(c), ...c.printData.bank } : liveBank(c); const companyOf = (c) => (c && c.printData && c.printData.company) ? { ...company, ...c.printData.company } : company; const stock = o.stock || bankOf(checks[0] || {}).stock || "top"; const pages = []; if (stock === "3up") { let pos = Math.min(3, Math.max(1, parseInt(o.startPos, 10) || 1)) - 1; let page = ""; checks.forEach((c) => { const b = { ...bankOf(c), stock: "3up" }; page += ckpFace(c, b, companyOf(c), 0, pos * 3.5, o); pos++; if (pos === 3) { pages.push(page); page = ""; pos = 0; } }); if (page) pages.push(page); } else { checks.forEach((c) => { const b = { ...bankOf(c), stock: "top" }; const co = companyOf(c); pages.push(ckpFace(c, b, co, 0, 0, o) + (o.alignment ? "" : ckpStub(c, b, co, 3.5, "PAYEE COPY — DETACH") + ckpStub(c, b, co, 7.25, "FILE COPY"))); }); } const font = cfg.micrFont ? `@font-face{font-family:"K2BMICR";src:url(${cfg.micrFont});}` : ""; const sid = (window.K2BStore && window.K2BStore.pageId()) || ""; // RC35 (brd): which store printed it return `${ckpEsc(o.title || "Checks")}
Print at 100% / Actual size, no headers or footers. Load ${stock === "3up" ? "3-per-page" : "check-on-top"} stock face ${o.faceUp === false ? "down" : "as your printer requires"}${o.fallback ? " · No MICR font found — this bank line is for a TEST only, not for real checks." : ""}${o.alignment ? " · ALIGNMENT TEST: print on plain paper, hold it over a blank check against the light." : ""}
${pages.map(p => `
${p}
`).join("")} `; }; /* ── open the print window (popup, else in-app overlay) ── */ const ckpOpen = (docHtml, title) => { if (window.K2BPrint && window.K2BPrint._capture(docHtml)) return; // RC35 (brd): the print test reads it (K2BPrint.lastDoc) let w = null; try { w = window.open("", "_blank", "width=900,height=1100"); } catch (e) { w = null; } if (w && w.document) { w.document.write(docHtml.replace("", `