150 lines
4.7 KiB
JavaScript
150 lines
4.7 KiB
JavaScript
// Letterhead configuration for the till.
|
|
//
|
|
// The POS uses a `letterhead_settings` row from the main WFDASH
|
|
// PocketBase (shared with the PDF flow). This module:
|
|
// 1. Caches the *list* of available letterheads in localStorage
|
|
// so the settings page can show the picker offline.
|
|
// 2. Caches the *active* letterhead (the one the till is currently
|
|
// running under) in localStorage so the till can render receipts
|
|
// and compute VAT without re-fetching on every sale.
|
|
// 3. Exposes a tiny global API that other POS scripts (pos-app.js,
|
|
// receipt.html, etc.) can use without each one re-implementing
|
|
// the cache + fetch dance.
|
|
//
|
|
// Like pos-config.js, the cache key prefix is `pos.letterhead.*`
|
|
// so it's clear what's till data vs. shop data when debugging.
|
|
window.PosLetterhead = (function () {
|
|
'use strict';
|
|
|
|
// Westcott Group is the canonical POS letterhead per the operator
|
|
// (per the 2026-09-04 audit). If the till has no active letterhead
|
|
// yet, we default-pick this id when the first letterhead list comes
|
|
// back. The id matches the PB row "5wezvypn6fy47p9" in the user's
|
|
// instance — see docs.
|
|
const DEFAULT_ID = '5wezvypn6fy47p9';
|
|
const DEFAULT_DISPLAY_NAME = 'WESTSCOTT GROUP OF COMPANIES';
|
|
|
|
const KEY_ACTIVE_ID = 'pos.letterhead.activeId';
|
|
const KEY_ACTIVE = 'pos.letterhead.active';
|
|
const KEY_LIST = 'pos.letterhead.list';
|
|
|
|
function lsGet(key) {
|
|
try { return JSON.parse(localStorage.getItem(key) || 'null'); } catch (e) { return null; }
|
|
}
|
|
function lsSet(key, val) {
|
|
try { localStorage.setItem(key, JSON.stringify(val)); } catch (e) { /* quota or disabled */ }
|
|
}
|
|
function lsDel(key) {
|
|
try { localStorage.removeItem(key); } catch (e) { /* ignore */ }
|
|
}
|
|
|
|
// -------- list (used by the settings picker) --------
|
|
|
|
function getCachedList() {
|
|
return lsGet(KEY_LIST) || [];
|
|
}
|
|
|
|
function setCachedList(items) {
|
|
lsSet(KEY_LIST, items);
|
|
}
|
|
|
|
// -------- active letterhead (used by sales + receipt) --------
|
|
|
|
function getActiveId() {
|
|
return lsGet(KEY_ACTIVE_ID) || null;
|
|
}
|
|
|
|
function getActive() {
|
|
return lsGet(KEY_ACTIVE) || null;
|
|
}
|
|
|
|
function setActive(item) {
|
|
if (!item || !item.id) return;
|
|
lsSet(KEY_ACTIVE_ID, item.id);
|
|
lsSet(KEY_ACTIVE, item);
|
|
}
|
|
|
|
function clearActive() {
|
|
lsDel(KEY_ACTIVE_ID);
|
|
lsDel(KEY_ACTIVE);
|
|
}
|
|
|
|
// -------- network calls --------
|
|
|
|
async function fetchList() {
|
|
const r = await window.posFetch('/letterhead');
|
|
if (!r.ok) throw new Error('letterhead list returned ' + r.status);
|
|
const j = await r.json();
|
|
const items = j.items || [];
|
|
setCachedList(items);
|
|
return items;
|
|
}
|
|
|
|
async function fetchById(id) {
|
|
if (!id) throw new Error('letterhead id is required');
|
|
const r = await window.posFetch('/letterhead/' + encodeURIComponent(id));
|
|
if (!r.ok) {
|
|
if (r.status === 404) throw new Error('letterhead ' + id + ' not found');
|
|
throw new Error('letterhead fetch returned ' + r.status);
|
|
}
|
|
const j = await r.json();
|
|
const item = j.item;
|
|
if (!item) throw new Error('letterhead response missing item');
|
|
setActive(item);
|
|
return item;
|
|
}
|
|
|
|
/**
|
|
* One-shot boot helper. Called from pos-app.js and settings.html.
|
|
* - If we have a cached active letterhead, return it immediately.
|
|
* - Otherwise, list letterheads; if Westcott Group is in the list
|
|
* auto-pick it; else pick the first active one.
|
|
* - Fetch the full row in the background so the cache stays warm
|
|
* (returns the fresh row if it differs).
|
|
*/
|
|
async function ensureActive() {
|
|
const cached = getActive();
|
|
if (cached && cached.id) {
|
|
// Refresh in the background — the till can keep using the cached
|
|
// copy while the network call is in flight.
|
|
fetchById(cached.id).catch(() => { /* keep cached on failure */ });
|
|
return cached;
|
|
}
|
|
// No active yet — list and pick a default.
|
|
let list = getCachedList();
|
|
if (!list.length) {
|
|
list = await fetchList();
|
|
}
|
|
const westcott = list.find(x =>
|
|
(x.display_name || '').toUpperCase().includes('WESTSCOTT') ||
|
|
(x.company || '').toUpperCase().includes('WESTSCOTT')
|
|
);
|
|
const pick = westcott || list[0];
|
|
if (!pick) {
|
|
// No active letterheads in PB. Mark this so the UI can show
|
|
// a clear "you need to set up a letterhead" message instead of
|
|
// a generic error.
|
|
clearActive();
|
|
return null;
|
|
}
|
|
return await fetchById(pick.id);
|
|
}
|
|
|
|
return {
|
|
// getters
|
|
getActiveId,
|
|
getActive,
|
|
getCachedList,
|
|
// setters
|
|
setActive,
|
|
setCachedList,
|
|
clearActive,
|
|
// network
|
|
fetchList,
|
|
fetchById,
|
|
ensureActive,
|
|
// constants (for debugging / display in settings)
|
|
DEFAULT_ID,
|
|
DEFAULT_DISPLAY_NAME,
|
|
};
|
|
})();
|