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
This commit is contained in:
2026-03-18 14:04:15 -06:00
parent 964823c8b4
commit c944c84939
7 changed files with 39 additions and 6 deletions
+2
View File
@@ -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);
+5
View File
@@ -346,6 +346,11 @@
</div>
</div>
<p class="settings-section-label">Signature</p>
<div class="form-group form-group-check">
<label><input type="checkbox" id="as-second-sig" name="second_signature"> Add second signature line (0.25&quot; above primary)</label>
</div>
<p class="settings-section-label">Logo</p>
<div class="form-group">
<label for="as-logo">Upload new logo</label>
+2
View File
@@ -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;
@@ -609,6 +610,7 @@ async function saveAccountSettings() {
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,
second_signature: document.getElementById('as-second-sig').checked ? 1 : 0,
logo_data: acctSettings.logoData || null,
};
+5 -3
View File
@@ -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);
+6
View File
@@ -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);
+1
View File
@@ -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')),
+16 -1
View File
@@ -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);