Add one-off next check number override
Pencil button next to "Next check: X" in the header opens a modal with a warning about sequence gaps/duplicates. Saves via new PUT /api/account/:id/check-no endpoint (sets current_check_no = next - 1).
This commit is contained in:
@@ -64,6 +64,26 @@ header {
|
||||
line-height: 1.4;
|
||||
}
|
||||
.btn-header-icon:hover { background: rgba(255,255,255,0.28); }
|
||||
.btn-header-inline {
|
||||
background: none;
|
||||
border: none;
|
||||
color: rgba(255,255,255,0.5);
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
padding: 0 0 0 4px;
|
||||
line-height: 1;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.btn-header-inline:hover { color: #fff; }
|
||||
.warning-box {
|
||||
background: #fef9c3;
|
||||
border: 1px solid #ca8a04;
|
||||
border-radius: 4px;
|
||||
padding: 10px 12px;
|
||||
font-size: 12px;
|
||||
color: #713f12;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* ── Toolbar ── */
|
||||
.toolbar {
|
||||
|
||||
+24
-1
@@ -13,7 +13,7 @@
|
||||
<select id="account-switcher" class="account-switcher" title="Switch account"></select>
|
||||
<button id="btn-account-settings" class="btn-header-icon" title="Account settings">⚙</button>
|
||||
</div>
|
||||
<span class="header-info">Next check: <strong id="current-check-no">—</strong></span>
|
||||
<span class="header-info">Next check: <strong id="current-check-no">—</strong><button id="btn-set-check-no" class="btn-header-inline" title="Set next check number">✎</button></span>
|
||||
</header>
|
||||
|
||||
<!-- View nav tabs -->
|
||||
@@ -383,6 +383,29 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Set next check number modal -->
|
||||
<div id="set-check-no-overlay" class="modal-overlay"></div>
|
||||
<div id="set-check-no-modal" class="modal" role="dialog" aria-labelledby="set-check-no-title">
|
||||
<div class="modal-header">
|
||||
<h2 id="set-check-no-title">Set Next Check Number</h2>
|
||||
<button id="btn-close-set-check-no" class="btn-icon" title="Close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="warning-box">
|
||||
<strong>Warning:</strong> Changing the next check number can create duplicate check numbers or gaps in your sequence. Only do this if checks were printed outside this system or your book was restarted.
|
||||
</div>
|
||||
<div class="form-group" style="margin-top:12px">
|
||||
<label for="set-check-no-input">Next check number</label>
|
||||
<input type="number" id="set-check-no-input" min="1" step="1" style="width:120px">
|
||||
</div>
|
||||
<div id="set-check-no-error" class="wizard-error" hidden></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btn-confirm-set-check-no" class="btn-primary">Set Number</button>
|
||||
<button id="btn-cancel-set-check-no" class="btn-ghost">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Deposit slide-in panel -->
|
||||
<div id="dep-panel-overlay"></div>
|
||||
<aside id="deposit-panel">
|
||||
|
||||
@@ -642,6 +642,49 @@ async function saveAccountSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Set next check number ─────────────────────────────────────────────────────
|
||||
|
||||
function openSetCheckNo() {
|
||||
const current = state.account ? state.account.current_check_no + 1 : 1;
|
||||
document.getElementById('set-check-no-input').value = current;
|
||||
document.getElementById('set-check-no-error').hidden = true;
|
||||
document.getElementById('set-check-no-overlay').classList.add('open');
|
||||
document.getElementById('set-check-no-modal').classList.add('open');
|
||||
document.getElementById('set-check-no-input').focus();
|
||||
document.getElementById('set-check-no-input').select();
|
||||
}
|
||||
|
||||
function closeSetCheckNo() {
|
||||
document.getElementById('set-check-no-overlay').classList.remove('open');
|
||||
document.getElementById('set-check-no-modal').classList.remove('open');
|
||||
}
|
||||
|
||||
async function saveSetCheckNo() {
|
||||
const errEl = document.getElementById('set-check-no-error');
|
||||
const input = document.getElementById('set-check-no-input');
|
||||
const next = parseInt(input.value, 10);
|
||||
if (isNaN(next) || next < 1) {
|
||||
errEl.textContent = 'Enter a valid check number (1 or higher).';
|
||||
errEl.hidden = false;
|
||||
return;
|
||||
}
|
||||
const btn = document.getElementById('btn-confirm-set-check-no');
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Saving…';
|
||||
try {
|
||||
await apiFetch('PUT', `/api/account/${state.activeAccountId}/check-no`, { next_check_no: next });
|
||||
state.account.current_check_no = next - 1;
|
||||
renderHeader();
|
||||
closeSetCheckNo();
|
||||
} catch (err) {
|
||||
errEl.textContent = err.message;
|
||||
errEl.hidden = false;
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.textContent = 'Set Number';
|
||||
}
|
||||
}
|
||||
|
||||
// ── Deposits ─────────────────────────────────────────────────────────────────
|
||||
|
||||
const depState = {
|
||||
@@ -1013,6 +1056,16 @@ function init() {
|
||||
document.getElementById('btn-cancel-acct-settings').addEventListener('click', closeAccountSettings);
|
||||
document.getElementById('acct-settings-overlay').addEventListener('click', closeAccountSettings);
|
||||
document.getElementById('btn-save-acct-settings').addEventListener('click', saveAccountSettings);
|
||||
|
||||
document.getElementById('btn-set-check-no').addEventListener('click', openSetCheckNo);
|
||||
document.getElementById('btn-close-set-check-no').addEventListener('click', closeSetCheckNo);
|
||||
document.getElementById('btn-cancel-set-check-no').addEventListener('click', closeSetCheckNo);
|
||||
document.getElementById('set-check-no-overlay').addEventListener('click', closeSetCheckNo);
|
||||
document.getElementById('btn-confirm-set-check-no').addEventListener('click', saveSetCheckNo);
|
||||
document.getElementById('set-check-no-input').addEventListener('keydown', e => {
|
||||
if (e.key === 'Enter') saveSetCheckNo();
|
||||
if (e.key === 'Escape') closeSetCheckNo();
|
||||
});
|
||||
document.getElementById('as-logo').addEventListener('change', e => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) { acctSettings.logoData = null; return; }
|
||||
|
||||
+18
@@ -84,6 +84,24 @@ app.get('/api/account/:id', (req, res) => {
|
||||
res.json(account);
|
||||
});
|
||||
|
||||
// PUT /api/account/:id/check-no - override the next check number
|
||||
app.put('/api/account/:id/check-no', (req, res) => {
|
||||
const db = require('./db/database');
|
||||
const account = db.prepare('SELECT id FROM account WHERE id = ?').get(req.params.id);
|
||||
if (!account) return res.status(404).json({ error: 'Account not found.' });
|
||||
|
||||
const next = parseInt(req.body.next_check_no, 10);
|
||||
if (isNaN(next) || next < 1) {
|
||||
return res.status(400).json({ error: 'Next check number must be a positive integer.' });
|
||||
}
|
||||
|
||||
// current_check_no is the last-used number; next check will be current_check_no + 1
|
||||
db.prepare("UPDATE account SET current_check_no = ?, updated_at = datetime('now') WHERE id = ?")
|
||||
.run(next - 1, req.params.id);
|
||||
|
||||
res.json({ next_check_no: next });
|
||||
});
|
||||
|
||||
// POST /api/account/setup - create a new account (wizard)
|
||||
app.post('/api/account/setup', (req, res) => {
|
||||
const db = require('./db/database');
|
||||
|
||||
Reference in New Issue
Block a user