Sarkar Tactical — system reference

The internal ops platform. Orders, production, materials, trim sheets, compliance, packing, shipping — all on one server, reachable from any browser on the LAN. This page is a quick reference for what’s where and how the parts fit together.

60
Frontend pages
31
Backend route files
22 k
Lines of code
40+
DB tables
0
Build steps

Scope Modules

Each module is one operational area — its own pages, REST endpoints and database tables. Roughly a dozen, covering goods-in through to the commercial invoice.

Orders & fulfilment 10 pages

Draft → finalised → produced → shipped lifecycle with transactional job-ref allocation and full attachment + checkpoint history.

  • Drafts with autosave, finalisation locks the ref
  • Line items, serials, file attachments, memos
  • Stage checkpoints + production timeline
  • Inline parcel logging, no navigation

Catalogue & products 8 pages

Three-tier hierarchy (category → item → variant) with bill-of-materials, usage costs, fabric/net/gross weights, ML rating, HS code, warranty & certificate of conformity tracking.

  • Per-variant rolling stock + reorder triggers
  • Copy / merge tools that preserve link integrity
  • Inline image upload + recipe-book PDF export

Production sheets 3 pages

Helmet, ballistic and carrier job sheets with auto-allocated serials, profile presets, material override per line, save-as-new-recipe one-click.

  • Pool-aware serial allocation (custom 3-letter pools)
  • Cross-link to source order from any sheet
  • Profile picker → auto-fill, amber-glow blanks

Materials & trims 6 pages

Per-roll fabric stock, ballistic panels, and a parallel trim-stock world (webbing, hook/loop, buckles, zips, elastic, bungee).

  • Idempotent imports from supplier price lists
  • Trim sheet library — reusable BOM templates
  • Per-size length columns, colour-agnostic recipes

Export compliance 5 pages

UK ECJU SIEL / OGL handling, ML ratings, HS codes, end-use certificates & per-shipment licence draw-down.

  • US/Plano standing SIEL with 7-product allow-list
  • Item ↔ licence-product mapping (custom → broad)
  • CIPL generator with auto-licensed naming

Packing & pallets 4 pages

Draft + final packing lists, box fit-matrix suggestions, pallet nester with 3D-aware stacking constraints, weight rollup.

  • Order import — PCS/CTN pre-filled from line qty
  • Landscape PDF exports with TOTALS rows
  • Pallet packing limit configurable per order

Stock & serials 6 pages

Movement ledger (in/out/transfer), labels grid, custom serial pools, allocation classifier, sticker-sheet PDFs.

  • Pool-aware allocation (default labels per pool)
  • Right-click context menu on serials in orders
  • Print queue / Printed log dual PDF exports

Memos & meetings 2 pages

Operations meeting notes with anchored job-ref references — click any ref in a memo to open the order in a new tab.

  • Legacy spans auto-upgraded to clickable anchors
  • Per-order "Related memos" section on every order

Pricing & quotes 4 pages

Catalogue-driven pricing with currency conversion, weight-based freight estimates, two-pass cost calc with QB lookup fallback.

  • Currency defaults from order header
  • Costing snapshot per quote (audit-friendly)

Compliance & quality 3 pages

Order checkpoints (Received → Licence → Plan → Manufacturing → Finishing → Shipping), CoC documents, inventory checks, data audit.

  • Auto-flagged missing-data rows in catalogue
  • Per-order checkpoint tick history

Operator stations 5 pages

Kiosk-friendly station views for warehouse, sales, materials — large tap targets, role-based landing pages, 4-digit PIN login.

  • Sales station: pick an order, fulfil, print labels
  • Warehouse: log deliveries, scan barcodes, mark printed

Visualisation 3 pages

Gantt-style order-progress timeline with stage colours, drag-to-reorder, range presets and zoom; pallet nester preview; PDF previews on every job sheet.

  • Responsive SVG axis locked to row bars
  • Stage segments coloured by completion %

Stack Architecture

Vanilla ES modules in the browser, Node + Express on the server, MySQL for state. No build step, no bundler, no framework dependency tree.

BROWSER · vanilla ES modules No build, no bundler. 60 HTML pages share /shared/ utility modules and a single CSS design system. shared/header.js shared/api.js shared/forms.js shared/pdf.js (lazy) back-button.js shared.css manifest.json (PWA) JSON / multipart EXPRESS API · 31 route modules Each domain (orders, catalogue, trims, us-licences, …) is one route file with its own ensureSchema(); FK + transaction discipline. orders.js catalogue.js trims.js us-licences.js parcels.js serials.js stock.js + 24 more MYSQL · 40+ tables Idempotent migrations · transactional row locks · per-domain FKs orders · catalogue · materials · trim_sheets · us_licence_shipments · … FILESYSTEM · uploads + backups User uploads served as static · hourly USB backups backend/uploads · USB drive (48h + 14d + 12m retention)

Stack at a glance

Node.js Express MySQL 8 mysql2/promise Vanilla JS (ES modules) Native Web Components CSS custom properties jsPDF (lazy) multer (uploads) Ubuntu systemd rsync + SSH Cloudflare Tunnel USB rolling backups

Views Selected views

HTML/CSS renderings of production views — same components, colours and typography as the live app. The URL in each frame links to the actual page.

Trim sheet — reusable BOM template with per-size lengths

/trim-sheet.html?id=40 · Bellator (Santa Ana) · carrier · 8 sections / 50 lines
Front Outside — 8 trim lines Size: Large
Trim typeWidthLength (cm)QtyNotes
Buckle25 mm2Side-release buckle
Webbing38 mm72
Webbing25 mm82
Buckle38 mm2Shoulder ROC buckle
Loop15 mm241
Webbing38 mm74
Buckle100 mm2Waist ROC buckle
Zip10 mm181

Eight sections covering the full carrier. Stored once; referenced by any order that needs a Bellator.

US/Plano SIEL — per-product balance with shipment ledger

/us-licences.html · Standing GBSIEL/2025/0019710/P · 9 shipments logged
Falcon ATV · ST-FLCN
922 / 1,000
ALPHA · ST-ALPHA
2,850 / 3,000
CTV · ST-CTV
2,496 / 2,500
Ranger Solo · ST-RSL
5,000 / 5,000
Live balance fed from us_licence_shipment_items joined to the licensed quantity — every logged shipment draws the per-product remaining down. Custom catalogue items (GPV, Bellator) ship as the closest licence family via a mapping table that’s read at CIPL-generation time.

Transactional ledger; read-time balance roll-up. The old multi-tab Excel tracker still exists as a backup.

Order progress — Gantt-style timeline with stage colours

/order-progress.html · 27 in-flight orders · 6 stages · zoom + pan
📋
P26-019
Santa Ana
📋
P26-018
I.I. & E.
📋
G26-030
WAFER
Received Licence Plan Manufacturing Finishing Shipping ⋮ today ▮ delivery

Six-segment bars; segment fill = proportion of stage checkpoints ticked. Drag a row to reorder; scroll-wheel zooms.

Commercial invoice + packing list (CIPL) — one button, two-page PDF

/cipl.html?orderId=31 · Pre-fills from order header + line items + linked licence product
📥 Pick order P26-019 · Santa Ana
🔄 Hydrate Catalogue + licence
📝 Preview / edit In-page modal
🖨️ Two-page PDF CI + PL · 1 click
When the order is on the standing US/Plano SIEL, the line items are automatically described as the licensed family (e.g. GPV → Sarkar Falcon ATV) with the correct ML rating + HS code from the licence product, not the catalogue item — one of the few places where the system actively rewrites your data on output to keep customs paperwork accurate.

One button; catalogue-name → licence-family rewrite happens at render time.

Ops Deployment

Deploys via a single shell script over SSH. Backups run hourly to a USB drive with rolling retention. Public access via Cloudflare Tunnel when needed.

One-command deploy

A single ./push.sh rsyncs the repo to the production server over SSH, runs npm install --omit=dev only when package.json changes, restarts the systemd service through a NOPASSWD sudoers entry, and polls /api/health for up to 10 s before declaring success. Total time: ~6 s for a frontend-only change.

One small script handles everything — copy the code to the server, install any new dependencies if needed, restart the app, and check it’s actually responding before saying “done”. About six seconds for a normal change.

Hourly USB backups, rolling retention

Cron-driven mysqldump + tar of backend/uploads to an external USB drive, with 48 hourly + 14 daily + 12 monthly snapshots kept. Survives Dell hardware failure without touching the cloud.

Every hour the entire database and uploaded files are copied to a USB stick plugged into the server. We keep two days of hourly copies, two weeks of daily copies, and a year of monthly copies. If the server breaks, we plug the stick into a new machine and we’re back.

Public access via Cloudflare Quick Tunnel

The internal-only LAN URL is fronted by a Cloudflare tunnel for off-network access. No port forwarding, no static IP, no firewall changes on the office router.

When someone needs to use the system from outside the office, a free Cloudflare service exposes the in-office address as a public web link. No router setup, no special internet line needed.

Health check & restart guards

Every deploy ends by polling /api/health for up to ten seconds; if the new build doesn’t come back, the script exits non-zero and prints the journalctl tail. Service is supervised by systemd with Restart=on-failure so a crash doesn’t take the warehouse offline overnight.

After a deploy, the script pings the app to confirm it’s alive before saying success — if not, you see the error log immediately. If the app crashes overnight the operating system restarts it automatically.

Role-based 4-digit login

Auth is a 4-digit PIN per user with role-keyed landing pages: admin → dashboard, sales → sales station, cutting → cutting log, stock → warehouse station. Keeps kiosk machines locked to a single screen by default.

Each person has a 4-digit PIN. After signing in they land on the page that matches their job — sales people on the sales screen, warehouse people on the warehouse screen, and so on. Kiosk machines stay locked to one view.

Audit trails on critical mutations

Order status changes, stock moves, and serial allocations all carry a created_by stamp pulled from the X-Sarkar-Employee header. The data-audit page reads the trail back as a single ledger.

Every important change (order status, stock in/out, serial assigned) records who made it. The Data Audit page reads the full history back as one timeline so you can see exactly who did what, when.

Deployment flow

💻 Edit on Mac VS Code Where new code is written
▶️ ./push.sh rsync + ssh Copies the new code to the server
📦 npm install if package.json changed Pulls in any new building blocks the code needs
🔄 systemctl restart sarkar-stock Restarts the app so the new code takes effect
/api/health ≤ 10 s polling Pings the app to confirm it’s alive
🚀 Live all users Everyone sees the update on their next page load

Pages Live pages

A handful of pages worth opening directly. Each is one HTML file plus shared modules, backed by its own endpoints and tables.

Dashboard

The numbered-tile home page. Role-aware landing. Composite tiles for Inventory and Materials with nested shortcuts.

Order edit

The largest screen in the app. Header autosave, line items, attachments, serials, compliance, parcels, pallets — all inline.

Order progress timeline

Gantt-style view of every in-flight order with stage-colour segments, zoom, pan, drag-to-reorder.

Trim sheet library

Reusable BOM templates. Per-size length columns, colour-agnostic via the garment-colour mapping table.

US Licence tracking

Per-product balance + shipment ledger + inline shipment dialog that allocates the next number at log-time.

Item ↔ licence mapping

Translates custom catalogue items into broad licence families for CIPL output. Autosave dropdowns, category filter, search.

Catalogue

Three-tier hierarchy with inline rename, copy/merge tools, variant drawer, image upload, recipe-book PDF.

Data audit

One page that flags every missing-data row in the system — missing weights, missing HS codes, orphaned stock.

CIPL generator

Commercial invoice + packing list. Two-page PDF, preview mode, licence-aware naming overrides.