| Invoice # | Date | Customer | Amount | Balance Due | Status |
|---|
| Est # | Customer | Total | Salesperson | Status |
|---|---|---|---|---|
| Loading… | ||||
| Customer | Invoices | Total Invoiced | Outstanding |
|---|
| Customer | Open Invoices | Outstanding | Avg Age (days) | % Unpaid |
|---|
| Invoice # | Date | Due Date | Customer | Amount | Balance Due |
|---|
| Account | Type | Balance |
|---|
The two columns m²/Box and Units/Box are used by the mobile scan page to calculate how many boxes a customer needs.
How to fill them in:
- Pick up the physical box of the product.
- Find the label — it will say something like "Coverage: 1.44 m²" or "6 tiles per box".
- Click the product card below to open the detail panel.
- Edit the m² per box (e.g.
1.44) and units per box (e.g.6) fields. - Click Save next to each field.
Note: Only fill in these fields for tile, flooring, panel and sheet products. Leave blank for adhesives, grout, trims, tools and accessories.
| Item | SKU | On Hand | Reorder Point | Excess Qty | Excess Value |
|---|
| Customer | Branch | Est # | Date | Total | Status | Salesperson | Preview | 💰 Bounty |
|---|---|---|---|---|---|---|---|---|
| Loading… | ||||||||
All Insights
Live business intelligence — charts, trends & KPIs across your branches.
Key Numbers
At-a-glance health check — refreshes live from QuickBooks.
Financial Performance
Margin, costs, revenue trend, cash position.
Customers & Receivables
Who buys, who pays, and how fast.
Operations & Inventory
What's moving, what's costing, what's stuck.
Active Alerts
Site Performance Comparison
All active companies side by side.
| Site | Revenue (Period) | Open AR | Overdue AR | Cash Balance | Overdue Invoices |
|---|
User Management
| Username | Full Name | Role | Store | Branch Access | WA Tag | Can Quote | Status | Actions |
|---|
Settings
Manage backups, integrations, scheduler health and team access.
| Company | When | Status | What was synced | Error |
|---|
| Sent | To | Report | Period | Status | Error |
|---|
🆘 I lost something — which layer do I use?
- The whole VM won't boot / OS broken → Layer 1 (Proxmox snapshot) if recent, else Layer 2 (PBS)
- Dashboard DB is corrupted or wrong data → Layer 3 (in-app maintenance backup, daily)
- I want photos/logo from a specific moment → Layer 4 (download .zip from a past day)
- I need a specific QuickBooks
.QBBbackup file → Layer 5 (Nextcloud Backups folder) - Lost the whole disk / hardware died → Layer 2 (PBS — restores to any Proxmox node)
askari0 → VM 206 → Snapshots.pbs-askari2 at https://192.168.0.15:8007 → Datastore /datastore..zip you can carry off-site (download, email, GDrive)..QBB backup files for each branch (Cape Town, Johannesburg), pushed by the QB Web Connector to the site's Nextcloud user.demo-dbn or demo-cpt → Backups/ folder. Live status shown below..QBB, open in QuickBooks → File → Restore.• Proxmox UI — askari1:8006 → VM 206 → Backup → pick snapshot → Restore
• CLI —
qmrestore pbs-main:backup/vm/206/<ts> <new-vmid>
qb.db from a chosen daily backup. Use when business data needs rollback (wrong customer edit, accidental delete) but the app itself is fine.
qb.db.before-restore-<timestamp> in the same folder. App restarts itself after restore. Browser will need ~5 s to reconnect.
Last maintenance run log
(none)
⚙️ Advanced — full zip download / upload restore
Database covers: quotes, lead tracker, container tracker, inventory coverage fields, news sources, users, schedules, SMTP & banking settings.
Scheduled email backup sends the database only (gzip compressed) — images are in the download backup.
.zip file from a previous download. Restores the database, product images, company logo, and .env config. Overwrites all current data.
📝 One-time Google Cloud setup — ~10 min (click to expand)
- Create a Google Cloud project at console.cloud.google.com/projectcreate — name it
Mizan Backups. - Enable the Google Drive API — APIs & Services → Library → Google Drive API → Enable.
- Configure OAuth consent screen — APIs & Services → OAuth consent screen:
- User Type: External
- App name:
Mizan, support email = your email - Skip scopes step. On Test users, add your Google account email.
- Leave app in Testing mode — no verification needed.
- Create OAuth Client ID — APIs & Services → Credentials → + Create Credentials → OAuth client ID:
- Application type: Web application
- Name:
Mizan - Add both Authorized redirect URIs:
https://mizan.tail95a3b4.ts.net/api/gdrive/oauth/callbackhttps://100.99.177.111/api/gdrive/oauth/callback
- Copy Client ID + Client Secret from the modal, paste below, click Save Credentials, then Connect Google Drive.
redirect_uri_mismatch → the URL you opened the dashboard with isn't in the list above. Add it in Cloud Console.
• 403 access_denied → your email isn't in the OAuth consent screen Test Users list.
{first_name}, {name}, {my_name}, {branch}, {balance}, {today}.
Executive Brief
AI-written cross-branch summary, pulled fresh from your live numbers.
🔎 Raw numbers used to write this brief
(none yet)
Help & Guides
Quick references and full manuals. Tap any card to open the guide.
📐 Room Calculator
Inside any inventory product, scroll to Room Calculator, enter Length × Width in metres (or total m² directly), pick a waste %, and it tells you boxes needed and whether stock is enough.
- 10% — straight lay, simple rectangle
- 15% — diagonal / herringbone, rooms with pillars or islands
- 20% — complex layouts, large-format tiles, feature patterns
🎨 Batch & Shade Codes
Tile from different production runs can have slightly different shade or size. The batch code on each box identifies the run — always supply tiles for one job from the same batch.
- The dashboard tracks batches per SKU and warns when stock crosses batches.
- Quote PDFs include the batch code so installers know what to look for.
- Always check batch + shade on the boxes before opening — replacements need the same code.
📦 Inventory Tools
- Search by name or SKU; filter by category, branch, or stock status.
- Photos — click a product to upload multiple images. They show in quotes, on the public scan page, and in the POS.
- Coverage — set m² per box and units per box on each product so the Room Calculator works.
- Cross-branch stock — a product card shows on-hand at every branch, not just the selected one.
- Export CSV — top-right of the inventory page.
🔳 QR Codes & Price Check
- Price Check tab → tap any product → "Print QR Label" for showroom displays.
- Customers scan the QR with their phone — opens a public page with product info + photos. No login.
- The staff scanner (
/scan/) is a phone-optimised version with stock info, internal pricing, and quick "add to quote" button.
📄 Estimates & Quotes
- Estimates tab → + New Quote → pick customer → add line items (search or scan) → set qty & price.
- Choose PDF template: Jericho (branded) · Classic (clean B&W) · Premium (with product photos).
- Click Preview to see the PDF. Edit if needed, then Save.
- Send by email (uses your SMTP) or WhatsApp (attaches the PDF as a document).
- Lead Tracker tab — every estimate appears here. Mark Hot/Mild/Cold, assign salesperson, set bounty for owner.
📱 WhatsApp Slips & Sending
- From the POS after a sale: tap 📱 WhatsApp slip, search a customer or type a number, hit send. Free if customer messaged you within 24h, otherwise sends as a utility template (~R0.12).
- From a quote: open the quote → Send → WhatsApp → pick customer. Attaches the quote PDF.
- From the WA gateway UI (
whatsapp-gw.tail95a3b4.ts.net): full messenger with conversation history, broadcast, contacts.
📊 Reports & Email Schedules
- Reports tab → pick a report type and date range → preview → email or download PDF.
- Daily Sales includes both Accrual (revenue earned) and Cash (money received) views, plus POS data.
- Settings → Email schedules — set up auto-send at any time, any days. One row per branch.
- Each schedule fires for one branch. To send multiple branches, tick the relevant ones in the same card — saves as two rows automatically.
👤 Users, Roles & Branches
- Superuser (you) — everything, plus user management and infra settings.
- Admin / Owner — full dashboard, all branches.
- Supervisor — own branch only, no user management, can void sales.
- Cashier / Staff — own branch only, modules you tick in user settings, voids need a manager PIN.
Settings → Users → Edit user → tick the modules they should see. The branch dropdown is locked to their assigned branch automatically.
📱 Phone as a Wireless Scanner
Any phone running the Scanner PWA (/scan/) can be paired to an open till and every QR/barcode it scans lands in the till's cart in real-time. Great for stocktake-style rings, customer-queue overflow, or a backup when a hardware scanner dies.
- On the till tablet, tap the 📱 icon in the top bar.
- A 6-digit code + QR appear. The code is good for 60 seconds.
- On the phone, open /scan/ → Till tab → enter the code (or scan the QR from the camera tab) → optionally name the phone ("Mary's phone") → Pair to till.
- Done. Switch the phone to the Scan QR tab and every scan goes straight to the till. The till's top bar shows a green ✓ chip with the phone's name.
What's built-in to keep it bulletproof:
- Idempotent scans — phone retries on flaky network won't double-add an item.
- 800ms dedup — phones double-trigger barcodes constantly; the second hit is silently ignored.
- Offline queue — phone offline mid-shift? Scans are stored locally and replayed when network returns.
- SSE reconnect — if the till's WiFi blips, scans are buffered server-side for 30s and replayed on reconnect.
- Session lasts 4 hours, then auto-expires. New pair on the same till revokes the old one.
- Brute-force protection — max 5 pair attempts per IP per minute.
- Audit log — every scan stored with device, label, sku, result. Admin can review.
The phone scanner page (/scan/) is still publicly accessible without a login — it just defaults to product-lookup mode until paired.
💳 Credit Limit Control (account sales)
When an account customer has a credit_limit set in QuickBooks (it syncs into the dashboard automatically), the POS keeps an eye on their outstanding balance and either warns or blocks an over-limit sale.
When a customer is selected at the till, a chip under their name shows the live status:
- 🟢 CREDIT OK — projected balance is under the warn threshold (default 80% of limit)
- 🟡 NEAR LIMIT — projected balance is ≥ warn threshold but still under the limit
- 🔴 OVER LIMIT — adding this cart would push them over their limit
Behaviour at checkout (POS Settings → Credit check mode):
- off — chip still shows, but no prompt; cashier can charge freely
- warn (default) — confirm dialog with the over-by amount; cashier can override on the spot
- block_with_pin — sale rejected unless a manager enters a 4-6 digit PIN; same PIN as voids/refunds
The chip stays hidden for walk-ins (no account) and for customers without a credit_limit set in QB.
📋 B2B Tax Invoice (SARS, sales ≥ R5000)
SARS requires that any sale of R5000 or more (incl VAT) be issued as a full Tax Invoice. The slip must show the buyer's name and address, and the buyer's VAT registration number if they're registered — otherwise the buyer can't reclaim the VAT.
The till handles this automatically:
- When the cart total crosses R5000, a navy banner appears above the charge buttons: "Tax Invoice required".
- Walk-in customer over R5000: tap Cash, Card or any payment method. Before the payment modal opens, a Buyer details dialog asks for:
- Buyer name (required — "Walk-in Customer" not accepted)
- VAT reg # (optional, but recommended — if the buyer is registered)
- Address (street, suburb, city, postal)
- Account customer over R5000: if the customer record already has VAT + address, the till uses those automatically (no extra prompt). Otherwise it asks like a walk-in.
- Slip prints/sends with a navy "TAX INVOICE" banner instead of "RECEIPT", and a BILL TO block showing the buyer's details.
- The QB transaction is unchanged — same SalesReceipt or Invoice as a normal sale, just the customer details are recorded.
The buyer details are frozen on the sale row — editing the customer record later doesn't change historic invoices. The Sales History detail view shows them under the line items.
↩️ Returns & Refunds
- POS sidebar → Sales History → find the original sale (search by sale # or customer).
- Click the sale to open it → Process return (yellow button, only shows for paid, non-refund sales).
- Set the qty to refund on each line. The "Already refunded" column shows what's been returned before (partial returns are fine — yellow row = partial, red = fully refunded).
- Pick the refund method:
- Cash — give money back from the drawer. Best for small cash sales.
- Card — refund to the customer's card on the terminal. Process the card refund separately on the speedpoint, then tick Card here so QB reflects it.
- Account — customer is on account; the return becomes a Credit Memo against their A/R balance (shows on their next statement).
- Credit note — issue a paper voucher to spend in-store next time. Does not push to QB (customer redeems it later).
- Add a short reason (optional but helpful for the audit log) → Confirm refund.
What happens behind the scenes:
- A new sale row is created tagged
-R1(e.g. PAR-2026-05-0007-R1) with negative amounts. - Stock is added back to the branch's inventory automatically.
- For cash/card refunds → a negative SalesReceipt goes to QB (reduces the deposit account).
- For account refunds → a CreditMemo goes to QB (reduces their outstanding balance).
- The original sale stays in QB unchanged — refunds are always separate reversing transactions for a clean audit trail.
Voids vs refunds — if you void a sale (instead of processing a return) and it's already in QuickBooks, the system now auto-creates the reversing entry too. No manual QB cleanup needed. The void status shows in the sale's detail view as "Void → QB: posted / queued / failed".
🖨 Thermal Printer Setup
- Plug the thermal printer to a network port or USB.
- POS → ⚙ Settings → Thermal Printer URL.
- For network: enter
192.168.0.50:9100(replace with printer IP). - For USB: select the device path from the dropdown.
- Tap Test print — a sample slip should come out.
If nothing prints, check: power, paper, LED status (red = error), and that the printer IP is reachable from the till device.
🔄 QuickBooks Sync & Data
- QuickBooks Web Connector (QBWC) on your QB Desktop PC pulls data every 15 minutes.
- Settings → Sync tab shows the last sync time and per-branch status.
- Click Force Sync to trigger an immediate pull.
- If sync stops: check the QB Desktop PC is on, QBWC is open (system tray), and QuickBooks is logged in.
| Invoice # | Date | Due Date | Customer | Amount | Balance Due | Status |
|---|---|---|---|---|---|---|
| Loading… | ||||||