From c944c849390d3016c21a446fe2d830719baeef19 Mon Sep 17 00:00:00 2001 From: Steve Dogiakos Date: Wed, 18 Mar 2026 14:04:15 -0600 Subject: [PATCH] Thinner check lines; second signature line toggle - Halve all check line thicknesses (line_thick * 0.5) - Add second_signature column to account table with runtime migration - Account settings toggle: enables a second signature line drawn 0.25" above the primary signature line, matching its width and thickness --- public/css/style.css | 2 ++ public/index.html | 5 +++++ public/js/app.js | 6 ++++-- src/app.js | 8 +++++--- src/db/database.js | 6 ++++++ src/db/schema.sql | 1 + src/services/pdfService.js | 17 ++++++++++++++++- 7 files changed, 39 insertions(+), 6 deletions(-) diff --git a/public/css/style.css b/public/css/style.css index 5175b70..d5bb7f0 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -305,6 +305,8 @@ td { color: var(--text-muted); } .form-group.required label::after { content: ' *'; color: var(--danger); } +.form-group-check { flex-direction: row; align-items: center; } +.form-group-check label { text-transform: none; font-weight: normal; font-size: 12px; letter-spacing: 0; cursor: pointer; display: flex; align-items: center; gap: 6px; } .form-group input { border: 1px solid var(--border); diff --git a/public/index.html b/public/index.html index 9455227..4d099a7 100644 --- a/public/index.html +++ b/public/index.html @@ -346,6 +346,11 @@ +

Signature

+
+ +
+

Logo

diff --git a/public/js/app.js b/public/js/app.js index 3c39603..46b2e73 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -572,6 +572,7 @@ function openAccountSettings() { f.elements.offset_right.value = a.offset_right || 0; f.elements.offset_up.value = a.offset_up || 0; f.elements.offset_down.value = a.offset_down || 0; + document.getElementById('as-second-sig').checked = !!a.second_signature; document.getElementById('as-logo').value = ''; document.getElementById('as-logo-preview').hidden = true; @@ -608,8 +609,9 @@ async function saveAccountSettings() { offset_left: parseFloat(f.elements.offset_left.value) || 0, offset_right: parseFloat(f.elements.offset_right.value) || 0, offset_up: parseFloat(f.elements.offset_up.value) || 0, - offset_down: parseFloat(f.elements.offset_down.value) || 0, - logo_data: acctSettings.logoData || null, + offset_down: parseFloat(f.elements.offset_down.value) || 0, + second_signature: document.getElementById('as-second-sig').checked ? 1 : 0, + logo_data: acctSettings.logoData || null, }; if (!payload.company1) { diff --git a/src/app.js b/src/app.js index 3d52140..bc805b6 100644 --- a/src/app.js +++ b/src/app.js @@ -39,7 +39,7 @@ app.put('/api/account/:id', (req, res) => { bank_name, bank_info1, bank_info2, bank_info3, transit_code, routing_number, account_number, offset_left, offset_right, offset_up, offset_down, - logo_data, + logo_data, second_signature, } = req.body; if (!company1 || !routing_number || !account_number) { @@ -52,6 +52,7 @@ app.put('/api/account/:id', (req, res) => { bank_name = ?, bank_info1 = ?, bank_info2 = ?, bank_info3 = ?, transit_code = ?, routing_number = ?, account_number = ?, offset_left = ?, offset_right = ?, offset_up = ?, offset_down = ?, + second_signature = ?, logo_data = CASE WHEN ? IS NOT NULL THEN ? ELSE logo_data END, updated_at = datetime('now') WHERE id = ? @@ -61,6 +62,7 @@ app.put('/api/account/:id', (req, res) => { routing_number, account_number, parseFloat(offset_left) || 0, parseFloat(offset_right) || 0, parseFloat(offset_up) || 0, parseFloat(offset_down) || 0, + second_signature ? 1 : 0, logo_data || null, logo_data || null, req.params.id ); @@ -68,7 +70,7 @@ app.put('/api/account/:id', (req, res) => { res.json(db.prepare( 'SELECT id, bank_name, bank_info1, bank_info2, bank_info3, transit_code, ' + 'routing_number, account_number, current_check_no, ' + - 'company1, company2, company3, company4, check_position FROM account WHERE id = ?' + 'company1, company2, company3, company4, check_position, second_signature FROM account WHERE id = ?' ).get(req.params.id)); }); @@ -78,7 +80,7 @@ app.get('/api/account/:id', (req, res) => { const account = db.prepare( 'SELECT id, bank_name, bank_info1, bank_info2, bank_info3, transit_code, ' + 'routing_number, account_number, current_check_no, ' + - 'company1, company2, company3, company4, check_position FROM account WHERE id = ?' + 'company1, company2, company3, company4, check_position, second_signature FROM account WHERE id = ?' ).get(req.params.id); if (!account) return res.status(404).json({ error: 'Account not found.' }); res.json(account); diff --git a/src/db/database.js b/src/db/database.js index bc546ca..8260079 100644 --- a/src/db/database.js +++ b/src/db/database.js @@ -93,6 +93,12 @@ if (!lfInfo.some(c => c.name === 'account_id')) { `); } +// Migration: add second_signature column to account +const acctInfo = db.prepare('PRAGMA table_info(account)').all(); +if (!acctInfo.some(c => c.name === 'second_signature')) { + db.exec('ALTER TABLE account ADD COLUMN second_signature INTEGER NOT NULL DEFAULT 0'); +} + // Create account_id indexes unconditionally (safe after migrations have run) db.exec(` CREATE INDEX IF NOT EXISTS idx_checks_account ON checks(account_id); diff --git a/src/db/schema.sql b/src/db/schema.sql index 3da463b..a687c93 100644 --- a/src/db/schema.sql +++ b/src/db/schema.sql @@ -23,6 +23,7 @@ CREATE TABLE IF NOT EXISTS account ( company4 TEXT, logo_data TEXT, signature_data TEXT, + second_signature INTEGER NOT NULL DEFAULT 0, blank_stock INTEGER NOT NULL DEFAULT 1, check_position TEXT NOT NULL DEFAULT '3-per-page', created_at TEXT NOT NULL DEFAULT (datetime('now')), diff --git a/src/services/pdfService.js b/src/services/pdfService.js index 8921d7a..fe6c484 100644 --- a/src/services/pdfService.js +++ b/src/services/pdfService.js @@ -159,7 +159,7 @@ function generateCheckPdf(account, checks, fields) { const endPos = pt(field.x_end_pos, field.y_end_pos); doc.moveTo(pos.x, pos.y) .lineTo(endPos.x, endPos.y) - .lineWidth(field.line_thick || 1) + .lineWidth((field.line_thick || 1) * 0.5) .stroke('#000000'); break; } @@ -211,6 +211,21 @@ function generateCheckPdf(account, checks, fields) { } } + // --- Second signature line --- + if (account.second_signature) { + const sigLine = bodyFields.find( + f => f.field_type === 'Line' && f.field_name.toLowerCase().includes('signature') + ); + if (sigLine) { + const p1 = pt(sigLine.x_pos, sigLine.y_pos - 0.25); + const p2 = pt(sigLine.x_end_pos, sigLine.y_end_pos - 0.25); + doc.moveTo(p1.x, p1.y) + .lineTo(p2.x, p2.y) + .lineWidth((sigLine.line_thick || 1) * 0.5) + .stroke('#000000'); + } + } + // --- MICR line --- const micrLine = formatMicrLine(account.routing_number, account.account_number, check.check_no); const micrPos = pt(0.3, MICR_Y_IN);