One file.
The whole project.
Nothing left to look up.
A single self-contained reference for MageTech Jewellery Smart — the vision and scope, the stack, the architecture decisions, the data model, all thirteen modules, every feature, the access rules, security controls, REST API, a working interface demo, the test evidence and the roadmap. No links to follow, no external requests, no build step.
Thirteen sections, one document
Everything below is drawn from the repository as it stands today — the requirements specification, the schema, the route table and the test suite — not from intent. Read it top to bottom or jump to a section.
What the system is
A jewellery-store management system for Indian jewellers running one or more counters, built around RFID-tagged stock and metal-rate-aware billing — and deployable on ordinary shared hosting, with no long-running processes.
★Vision & tagline
Smart Billing. Smarter Inventory. RFID-Powered Jewellery Management.
POS/counter billing · inventory and stock control · RFID tagging · product and catalogue management · metal rates · purchases and supplier settlement · customer management · reporting · analytics · multi-branch multi-tenant operation · role-based access · audit trail · backups.
✓Success criteria
- Counter bill latency under 300 ms (warm DB, cached assets)
- 10+ concurrent users per branch
- No long-running processes — shared-hosting uptime
- Reload-safe counter: the cart is server-held
- 100% of statutory GST fields on every invoice
- RFID scan → verify under 500 ms
+In scope
Everything in the two cards above, plus multi-tenant operation so a group can run several shops from one install, and a read-only REST API for devices and integrations.
−Explicitly out of scope
Redis · Docker/containerisation · JVM services · PostgreSQL · WebSockets/SSR · Spatie packages · a Node front-end. Each was excluded because the deployment target is cPanel/shared hosting. Repairs & karigar tracking were dropped from scope (no section owned them) rather than left as an open promise.
Every dependency, chosen against a constraint
The deployment target is shared hosting with no long-running processes. That one rule eliminated Redis, Docker, JVM services, PostgreSQL, WebSockets and a Node front-end before a line was written — and shaped everything that remained.
| Layer | Choice | Why, and what it rules out |
|---|---|---|
| Runtime | PHP 8.3 · Laravel 13 | Runs on any cPanel host. Rules out JVM services and container-only tooling. |
| Database | MariaDB / MySQL · utf8mb4 | The shared-hosting standard; money stored as integer paise. Rules out PostgreSQL. |
| Front-end | Blade · Livewire 3.8 · Alpine · Tailwind 4 | Server-rendered with local interactivity. Rules out an SSR/Node front-end. |
| Real-time | Polling + Livewire | No persistent connection. Rules out WebSockets and SSE. |
| Queue & cache | database queue · file cache & session | No daemons to supervise. Rules out Redis as a requirement. |
| Scheduling | Cron → schedule:run | One entry in crontab; no schedule:work process in production. |
| API auth | Laravel Sanctum | Personal access tokens carrying the owner's own permissions. |
| Dompdf | Statutory invoices, GSTR sheets and reports rendered server-side. | |
| Charting | Chart.js 4 | Bundled locally — no chart CDN at runtime. |
| Fonts | Figtree · Playfair Display | Self-hosted woff2; a test fails the build on any external font request. |
| Auth scaffold | Laravel Breeze, fully re-skinned | Standard flows, brand-new face. |
| Domain logic | Hand-written tenancy, permissions, audit, backup | No Spatie packages — smaller, auditable, on purpose. |
▣Backend shape
- 48 migrations · 39 models · 47 controllers
- 92 support classes (enums, services, value objects)
- 143 Blade views · 184 web routes
- Middleware: SecurityHeaders, ResolveTenant, EnsurePermission
◈Front-end shape
- Vite 8 build, assets committed — nothing to build at deploy
- Tailwind 4 with
brand/navy/gold/cyannamespaces - Alpine for small client behaviours
- Zero external CDN requests, enforced by test
⚒Engineering tooling
- PHPUnit 12 · Collision · Laravel Pint
- 732 tests / 3,103 assertions, all green
- Middleware order pinned by a dedicated test
laravel/paofor agent-readable test output
Decisions that shape everything
Six confirmed architecture decisions govern the whole codebase. They are recorded in docs/REQUIREMENTS.md §3 and asserted by tests, so a refactor that breaks one fails the suite rather than silently changing the product.
| Decision | Detail | Consequence |
|---|---|---|
| Tenancy resolution | Path → domain → session → signed-in user's tenant → default | The URL segment wins, but a deliberate default never outranks a known owner. No public signup path creates a tenant. |
| Tenant storage | Single MariaDB database, tenant_id global scope | One backup, one migration path. User carries the scope too, so provider lookup is confined by construction. |
| Branches | A tenant owns many branches; branch_id on stock and sales | Branch is a separate axis from tenant — group reporting falls out of the schema. |
| RBAC | Named roles, fixed permission lists in code | No UI can grant a capability the repository does not contain. No privilege-escalation surface to guard. |
| First admin | php artisan magetech:install-admin | No default credentials ship anywhere; no route can mint an owner. |
| Audit & backups | Custom append-only table; custom zip archive | Audit rows throw on update/delete. Archives land in storage/app/private/backups, outside the web root. |
Middleware order is a security property
The tenant resolver must run after the session starts and before route-model binding. Global middleware fires too early (no session store); resolving after SubstituteBindings is worse and quieter — the scope would be inert while another business's row bound successfully.
tenant_idtests/Feature/MiddlewareOrderTest.php pins this ordering directly, because it is a security property rather than a style preference. A reordering that looks harmless would otherwise bind another tenant's row instead of 404ing.Forty-six tables, two invariants
48 migrations create 46 business tables plus the framework's own cache, jobs and sessions. Two rules hold across all of them: every tenant-owned row carries a non-null tenant_id filtered by a global scope, and a balance is only ever written by the one writer the module names for it.
TTenancy & identity
tenants— slug, name, domains, locale, timezoneusers— tenant-scoped, role enumbranches,counters— prefixes per branchbusiness_settings— one row per tenantaudit_logs— append-only, immutablepersonal_access_tokens— Sanctum API keys
PCatalogue & rates
products— SKU, HSN, two GST rates, pricing modeproduct_variants— weight, fineness, barcode, priceproduct_images— credited photographyproduct_categories— hierarchical, cycle-safemetal_rates— append-only, effective-dated
SStock
stock_movements— append-only, reference-linkedstock_levels— cached balance, one writerstock_counts+ lines — post whole or not at all- Transfers write a row pair: out at source, in at destination
RRFID
rfid_tag_batches— sequentialMT-codes, closes for goodrfid_tags— active / lost / retired / reissuedrfid_tag_bindings— one tag per variant, history keptrfid_scan_sessions+ results — every read kept verbatim
BBilling & sales
counter_sessions— open/close, counted cash, variancesales_invoices+ lines + paymentsheld_bills— stored as items, re-priced on resumecredit_notes+ lines — reversed out of stockloyalty_point_entries— append-only
LParties, purchases & system
customers/suppliers+ ledger entriespurchase_orders→goods_receipts→purchase_invoicesmetal_bookings— rate-lock, settle oncejobs,sessions,cache
| Write discipline | Single writer | What it prevents |
|---|---|---|
| Stock balance | Support\Inventory movement writer | A controller incrementing a quantity the ledger doesn't know about |
| Metal rate history | MetalRateController / importer | Retroactive price changes rewriting old bills |
| Audit rows | Insert-only; update/delete throw | Tampering with the record of who did what |
| Invoice numbers | Per-branch, per-FY allocator | Gapless numbering; duplicate documents |
| Loyalty balance | loyalty_point_entries sum | Two screens disagreeing about a customer's points |
Thirteen modules, 52 sections, all delivered
The system is specified section by section and every section is built. Each module below lists what it does at the counter and in the back office — this is the functionality a jewellery business gets on day one.
1 · Dashboard
§1.1–1.3A role-aware home screen: what each user sees depends on their job, and every figure reads live from the tables the rest of the system writes — no stale summaries.
- Today's sales, stock on hand, bound tags, party dues
- Five alert types incl. low stock & flagged scans
- Shortcuts that check permission before showing
2 · Products & Catalogue
§2.1–2.5Product master with variants and images, hierarchical categories that refuse to become cyclic, metal and purity as closed enums with fineness as data, and two pricing modes.
- Multi-image upload, per-variant SKU/barcode/price
- HSN codes, making %, wastage, purity (22K/18K…)
- Category reorder & drag-order maintenance
3 · Inventory & Stock
§3.1–3.5An append-only stock ledger — nothing is ever overwritten — plus per-location transfers, physical counts with variance reason codes and purity-adjusted valuation.
- Stock register by branch/location/cut
- Manual adjust with reason codes
- Count sheets: create → add lines → post/cancel
4 · RFID Tagging
§4.1–4.5The module other jewellery software doesn't have: tag batches, EPC binding, scan sessions with manifests, printable label sheets and a full tag lifecycle.
- Batch create/close/print, bind & unbind
- Scan session: reads → complete/abort
- Found / lost / retire / reissue with history
5 · Billing / POS
§5.1–5.6The counter. Open a shift with a float, build a cart on the server, hold and resume bills, split payments, run exchanges, then print statutory or thermal output.
- Counter open/close with counted-cash variance
- Hold/resume, quick customer, barcode & RFID search
- Exchange & return against the original bill
6 · Sales & Invoices
§6.1–6.4Every invoice numbered gaplessly per financial year per branch, rendered to PDF, with registers cut by day, counter and shift — and credit notes for returns.
- GST PDF, 80 mm thermal and A5 print
- Day book / counter / shift registers
- Credit note with reason codes & withdrawal
7 · Customers
§7.1–7.4Customer profiles with GSTIN-derived party type, purchase history read from actual bills, advances and dues, printable statements and a loyalty scheme.
- Ledger entries & closing-balance statement
- Earn / redeem loyalty points at the till
- Party past 30 days surfaces on the dashboard
8 · Suppliers
§8.1–8.3Supplier profiles and a payable ledger where advances are kept as their own entry type — so ageing can never count the same rupee twice.
- Payable ageing without double-counting
- Period-based printable statements
- Manual entries with audit attribution
9 · Purchases
§9.1–9.4Procurement as a state machine: draft → approved → placed → received. Goods receipts are the only place inbound stock moves, and metal bookings lock a rate for a period.
- PO line editing, approval and placement
- GRN with over/short variance explanation
- Metal bookings create/settle/cancel
10 · Metal Rates
§10.1–10.3Effective-dated, append-only rates — no retroactive overwrite ever. Live screen, history, audited manual override and an all-or-nothing CSV import.
- Per metal / purity, effective from a date
- History with no retroactive edits
- CSV import: template, validate, all-or-nothing
11 · Reports
§11.1–11.3Sales, stock, purchases and party ageing as CSV, plus GSTR-1 and GSTR-3B working sheets bucketed by HSN and rate — exportable and printable.
- 4 report families, CSV export each
- GSTR-1 & GSTR-3B as CSV and PDF
- HSN + rate bucketing for filing
12 · Analytics
§12.1–12.2Period-over-period comparison with a least-squares seven-day projection labelled as a projection, plus fast/slow/dead stock and margin against lifetime cost.
- Sales trend vs previous window
- Fast / slow / dead stock classification
- Margin on lifetime weighted-average cost
13 · Settings & Admin
§13.1–13.5Business profile and GST, branches and counters, users with a read-only role matrix, tenancy scoping, a filterable audit log and tenant backups with restore.
- Branch CRUD with own invoice prefixes
- Users: create/edit/disable, last-owner guard
- Backup create / download / restore
Every feature, plainly listed
203 endpoints in total — 184 web across 13 modules, 13 authentication endpoints and 6 REST API endpoints. Below is what a user actually meets on screen, grouped the way they experience it.
| Area | Routes | What you can do |
|---|---|---|
| Dashboard | 2 | Role-aware cards (today's sales, stock on hand, bound tags, party dues); alerts for low stock, flagged RFID scans, bindable tags, parties not seen in 30 days and bookings expiring within a week; shortcuts that check both permission and route existence. |
| Catalogue | 21 | Create/edit/delete products; multi-image upload; variant rows each with own SKU, barcode and price; category create, edit, delete and reorder; metal rate create, CSV import with template download, and effective-dated history. |
| Inventory | 13 | Stock screen with location cut; movement register; manual adjustment and branch-transfer forms; full count workflow — create sheet, add lines, post or cancel — with independent piece and weight tallies. |
| RFID | 22 | Tag batches: create, close, print, label sheet; per-tag bind, unbind, mark found, mark lost, reissue; scan sessions: start, add reads, complete, abort, view reads; bindable-tag picker for the counter. |
| Billing / POS | 18 | Counter open with opening float and close with counted cash and variance; till with line add/remove; barcode & RFID search; quick customer create; hold, resume and clear; exchange panel; post bill and reprint. |
| Sales & returns | 13 | Invoice register with day/counter/shift cuts; invoice detail; PDF download; 80 mm thermal and A5 print; return creation against a specific bill; credit note detail, print and cancel. |
| Parties | 18 | Customer and supplier CRUD; manual ledger entries; printable statement with closing balance; purchase history read straight from posted bills; customer picker live on the till. |
| Purchases | 33 | Purchase orders draft → approve → place → cancel with line-level editing; goods receipts with over/short variance explanation; metal bookings create/settle/cancel; purchase invoices post, settle and cancel with per-line returns. |
| Reports | 15 | Sales, stock, purchases and parties — each with CSV export — plus GSTR-1 and GSTR-3B as CSV and PDF, bucketed by HSN and tax rate. |
| Analytics | 2 | Sales trend with previous-window comparison and a labelled seven-day projection; inventory fast/slow/dead classification; margin against lifetime weighted-average cost. |
| Settings | 24 | Business profile and GST details; branch CRUD with own invoice prefixes; user CRUD with last-owner and last-branch guards; read-only role matrix; filterable audit log; personal access API tokens; backup create, download, restore and delete. |
| Profile | 3 | Name, email and password change for the signed-in user. |
| Authentication | 13 | Login, logout, forgot password, reset password, email verification, password confirmation, registration. |
| REST API | 6 | Sanctum-token endpoints for products, stock, bills and rates — for integrations, handhelds and future mobile clients. |
Business rules the system enforces for you
⏱State machines
- Counter session must be open before a bill exists — one shift per till
- Closing shows counted cash against expected and records the variance
- Purchase order: draft → approved → placed → received
- Goods receipt posts only with an explained variance
- Credit note is withdrawable: stock returns, account corrected
- RFID batch closes for good; a closed batch refuses a reprint
- Scan session accepts no reads once closed
⚑Guards you can't bypass
- The last active owner can't be deactivated
- Nobody deletes or demotes their own account
- The last branch can't be deleted
- Super-admin status is never accepted from a form
- Payments beyond a supplier's payable are refused
- Advances are a separate entry type, never mixed into ageing
- Rate history cannot be edited retroactively
⇩Outputs you get
- GST invoice PDF with every statutory field
- 80 mm thermal receipt via the browser print dialog
- A5 invoice print
- GSTR-1 and GSTR-3B CSV + PDF
- Sales / stock / purchase / party CSV exports
- Customer & supplier statements with balance
- RFID label sheets and count sheets
- Nightly zipped backup: database + files
Feature checklist
A flat, scannable list of what is in the box today.
Five roles, thirty-three permissions
Permissions are string cases in App\Support\Auth\Permission, not rows in a table — so an authorisation decision always traces to a literal in the repository, and no role can acquire a capability through the UI. There is deliberately no permission editor.
| Permission | Owner | Manager | Cashier | Accountant | Stockroom |
|---|---|---|---|---|---|
dashboard.view | ● | ● | ● | ● | ● |
products.view · rates.view · inventory.view · rfid.view | ● | ● | ● | ● | ● |
products.manage | ● | ● | — | — | ● |
rates.manage | ● | ● | — | — | — |
inventory.manage | ● | ● | — | — | ● |
rfid.manage | ● | ● | — | — | ● |
billing.create · billing.hold · billing.reprint | ● | ● | ● | — | — |
billing.discount · billing.cancel | ● | ● | — | — | — |
sales.view | ● | ● | ● | ● | — |
sales.view_all · sales.return | ● | ● | — | ● | — |
customers.view | ● | ● | ● | ● | — |
customers.manage | ● | ● | ● | — | — |
suppliers.view · purchases.view | ● | ● | — | ● | ● |
suppliers.manage · purchases.manage | ● | ● | — | — | ● |
reports.view · analytics.view | ● | ● | — | ● | — |
reports.financial | ● | — | — | ● | — |
settings.view | ● | ● | — | — | — |
branches.manage · users.view · audit.view | ● | ● | — | — | — |
settings.manage · users.manage · backups.manage | ● | — | — | — | — |
OOwner
Full access, including users, settings and backups. 33 / 33 permissions.
MManager
Runs the outlet day to day, without backups or user provisioning. 29 permissions.
CCashier
Bills at the counter and handles customers. 11 permissions — no discount, no cancel, no reports.
AAccountant
Reporting, GST working sheets and party ledgers. 12 permissions — read-only across the book, no billing.
SStockroom
Stock, RFID tags, product records and purchases. 11 permissions — no billing, no sales.
⊕API tokens
A token carries its owner's permissions and nothing more — a cashier's token can no more read a report than the cashier can in a browser.
Hardening as middleware, not a checklist
SecurityHeaders runs on every response — error pages, downloads and the health endpoint included, because a header that only guards the screens that render often is one an attacker simply avoids.
| Control | What it does |
|---|---|
| Content-Security-Policy | default-src 'self' with object-src 'none', base-uri 'self', frame-ancestors 'self', form-action 'self'. Scripts and styles from any other origin are refused outright. |
| Permissions-Policy | Eight sensors named as unavailable: accelerometer, camera, geolocation, gyroscope, magnetometer, microphone, payment, USB. |
| Transport & framing | X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, Referrer-Policy: strict-origin-when-cross-origin, HSTS where the request is already https. |
| Rate limiting | A named api limiter at sixty requests a minute per user, applied to every API route. |
| Error handling | Branded 403, 404, 419, 429 and 500 pages instead of framework traces; /up for probes. |
| Tenant isolation | Global tenant_id scope on every owned table, including User — reach is confined by construction. |
| Audit trail | Append-only: updates and deletes throw a LogicException rather than silently corrupting who did what. |
| Backups | JSON + manifest inside a zip under storage/app/private/backups — outside the web root. Restore refuses another business's file and refuses column drift before the first delete. |
| Bootstrap | Owners exist only through magetech:install-admin. No default credentials ship; no route can mint an admin. |
| Secrets | .env is git-ignored; API tokens are shown once in plaintext and revocable instantly from settings. |
Six read-only endpoints, same permissions
A Sanctum-authenticated, read-only surface for till displays, stock devices and reporting hooks. It answers in one shape, prices in integer paise, and carries the caller's own permissions — the token grants nothing its owner does not already hold.
auth:sanctumbearer tokentenant scopeglobalthrottle:api60 / min / user⇄Response contract
Every response is a single JSON object: data for the payload, meta for pagination and timing. Money is integer paise, dates are ISO-8601, errors use the same envelope with a stable machine-readable code.
GET /api/products— list & filterGET /api/products/{id}— detail with variantsGET /api/stock— levels by locationGET /api/rates— effective metal ratesGET /api/invoices— recent documentsGET /api/invoices/{id}— one document
⛨What it deliberately isn't
- No writes — billing and stock stay in the application where the guards live
- No public registration; tokens are minted per user from settings
- No separate permission model to drift from the UI's
- No unauthenticated endpoint of any kind
- Rate-limited at 60 requests/minute/user
Integration points for handhelds, kiosks and BI tools — with the same tenancy and role rules as a browser session.
The interface, demonstrated
Four working demonstrations of the real screen layouts — the dashboard a manager opens, the till a cashier lives in, the RFID scan a stockroom runs and the report an accountant files. Switch tabs; the animations replay.
Good morning, Priya
Owner · Jaipur — Bapu Bazaar · 02 Oct 2026
Sales — last 7 days today highlighted
Alerts
Bill · Till 1
Customer: Meera Sharma · 98290… · Loyalty 2,140 pts
Scan-to-verify target: < 500 ms per tag. Each read is matched against the batch manifest; anything not expected is flagged for review rather than silently accepted.
GSTR-1 · September 2026
B2B + B2C summary · HSN bucketed · GSTIN 08ABCDE1234F1Z5
| HSN | Description | Taxable value | Rate | CGST | SGST | Total |
|---|---|---|---|---|---|---|
| 7113 | Gold jewellery, 22K | ₹18,42,500 | 3% | ₹55,275 | ₹55,275 | ₹19,53,050 |
| 7113 | Silver articles | ₹1,86,400 | 3% | ₹5,592 | ₹5,592 | ₹1,97,584 |
| 7114 | Gold jewellery, 18K | ₹4,12,900 | 3% | ₹12,387 | ₹12,387 | ₹4,37,674 |
| 7102 | Diamonds, unstudded | ₹6,75,000 | 0.1%+0.1% | ₹675 | ₹675 | ₹6,76,350 |
| 9988 | Making charges (labour) | ₹2,41,600 | 5% | ₹12,080 | ₹12,080 | ₹2,65,760 |
Reconciliation
Proven by tests, not promises
Every milestone from M0 to M9 is built and runnable. The evidence sits in the repository: a PHPUnit suite that covers the state machines, guards and permissions, style checks that stay clean, and a production build that compiles.
M0 Foundation done
Laravel 13 scaffold, toolchain, brand design system, self-hosted fonts, test harness.
M1 Auth & tenancy done
Breeze re-skinned, tenant resolution chain, global scope, role permissions in code.
M2 Catalogue done
Products, variants, images, categories, metal & purity enums, HSN, pricing modes.
M3 Inventory done
Append-only ledger, transfers, adjustments with reasons, count sheets and valuation.
M4 Parties done
Customers and suppliers, ledgers, statements, advances, purchase history, loyalty.
M5 Purchases done
Orders, goods receipts with variance, metal bookings, purchase invoices and settlement.
M6 Rates done
Effective-dated append-only rates, live/history screens, audited overrides, CSV import.
M7 Billing done
Counter sessions, server-held cart, holds, exchange, split payment, thermal & statutory output.
M8 Sales & reports done
Registers, PDF invoices, credit notes, CSV reports, GSTR-1 and GSTR-3B.
M9 Dashboard, backups, hardening done
Role-aware dashboard, five alert types, nightly backups with restore, middleware ordering pinned by tests.
⛨Security posture
- Sanctum API auth; hashed passwords; session hardening
- Content-Security-Policy, HSTS, nosniff on every response
- Permission checked in middleware — before the controller
- Tenant scope is a global query scope, not a request filter
- Backups stored where the web root cannot serve them
- No default credentials: first owner via artisan command
⚙Runs anywhere cheap
- PHP 8.3 + Laravel 13 + MariaDB — nothing exotic
- Blade + Livewire + Alpine + Tailwind, compiled at deploy
- No Redis / queue worker / Node SSR / Docker / WebSockets
- Cron only — no
schedule:workprocess - File cache & session drivers, database queue
- Self-hosted fonts: zero third-party requests
✓Definition of done
- Full suite green — 732 tests, 3,103 assertions
- Laravel Pint style check clean
npm run buildsucceeds, assets committed- No external network request in devtools
- Statutory GST fields verified present
- Middleware order asserted by an automated test
What's next, honestly listed
Nothing below is broken — it is scope that has not been opened yet. These are the capabilities a live jewellery shop will ask for next, ranked by how soon it will be asked for.
High value Loyalty configuration screen
Loyalty is built and working — earn and redeem already run at the till — but the four settings that control it have no screen yet, so switching it on for a shop needs a developer today.
High value Barcode label printing
Products carry barcodes and the till searches on them, but only RFID label sheets can be printed. A jeweller not using RFID still needs adhesive barcode labels at the counter.
High value Offline billing
Billing is refresh-safe — the cart lives on the server — but a dead connection stops sales. A queue that replays transactions when the line returns is the largest remaining engineering item.
Medium Notifications & reminders
Low stock, flagged scans and overdue parties appear as dashboard alerts only. Email/SMS/WhatsApp delivery, birthday and anniversary reminders and due-payment nudges are not wired up yet.
Medium Estimates & quotations
A per-branch estimate prefix is already stored in the schema, but no screen writes it. Quotation-to-bill conversion, expiry and customer acceptance are unimplemented.
Medium GSTR filing integration
GSTR-1 and GSTR-3B are working sheets — CSV and PDF a human files in the portal. Direct IRN e-invoicing and e-way bills are an external integration, not an app feature.
Medium Custom roles
Roles are deliberately fixed in code so no screen can grant a privilege the code doesn't have. A shop wanting "senior cashier — discounts but no reports" would need a permissions editor and a security decision.
Medium Custom tenant domains UI
The resolver reads tenants.domains as step two of five, but no screen sets it — multi-shop groups running one custom domain per outlet need database access today.
Low Languages (Hindi/regional)
Every string in the UI is already wrapped for translation — 2,094 call sites — but no language files exist yet, so everything falls back to English. Adding copy is a content job, not a code job.
Low PWA offline shell
A web manifest and install shortcuts ship, but there is no service worker — opening the app with no signal shows the browser's error page rather than a cached shell.
Low Queue-backed work
app/Jobs does not exist. Backups, rate imports and PDF generation run inside the request. The database queue driver is already configured, so adding jobs is cheap when something becomes slow.
Low Repairs & karigar tracking
Present in the original outline, then dropped because no section owned it. Reopening it is a genuine module with its own lifecycle — it needs a spec revision, not a finishing touch.
Where everything lives
The repository layout behind this document, the counting rules for the numbers used throughout, and a glossary of the domain terms that jewellery retail uses differently from generic e-commerce.
📂Repository layout
app/
Console/Commands/ install-admin, backup
Http/Controllers/ 47
Http/Middleware/ SecurityHeaders, ResolveTenant, …
Models/ 39
Support/
Auth/ Permission, Role
Billing/ Inventory/ Rfid/ Parties/
Reports/ Tenancy/ Backup/ Audit/ Dashboard/
database/migrations/ 48
resources/views/ 143 Blade views
routes/ web, auth, api, console
tests/Feature/ 732 tests · 3,103 assertions
docs/ REQUIREMENTS.md (52 sections)
∑Counting rules
- 52 sections — 3+5+5+5+6+4+4+3+4+3+3+2+5 across 13 modules
- 203 endpoints — 184 web + 13 auth + 6 API
- 46 tables — business tables only; framework cache/jobs/sessions excluded
- 33 permissions — enum cases in
Permission.php - 732 tests / 3,103 assertions — full suite, green at time of writing
- 2,094
__()call sites — translation-ready, nolang/files yet
Source of truth: docs/REQUIREMENTS.md v1.3, reviewed 2026-09-30.
| Term | What it means in this system |
|---|---|
| Tenant | One business (a shop or group). Every owned row carries tenant_id; the resolver picks it from path, domain, session or signed-in user. |
| Branch | An outlet inside a tenant, with its own invoice prefixes and counters. A separate axis from tenant, so group reporting falls out of the schema. |
| Counter session | A shift: opened with a float, closed against counted cash. A bill cannot exist outside one. |
| Metal rate | Effective-dated price per metal and purity. Locked into a bill at creation; history is append-only. |
| Purity / fineness | 22K, 18K… as an enum with numeric fineness as data, so valuation adjusts for purity rather than assuming pure metal. |
| Making & wastage | Labour percentage and wastage percentage applied to gold value — the two numbers that make a jewellery bill different from a retail bill. |
| RFID tag | A UHF EPC bound to one product variant, with a lifecycle: active → lost / retired → reissued. History is kept across every rebind. |
| Scan session | A timed read against a manifest: every read stored verbatim, unmatched reads flagged for review rather than accepted. |
| Credit note | A return written against the bill it reverses — stock comes back out and the account is corrected. |
| Metal booking | A rate-lock commitment with a supplier: create → settle → cancel, settling once. |
| Held bill | A paused cart stored as items; re-priced against the current rate on resume. |
| GSTIN / HSN | State-coded tax identity and classification code; drives GSTR-1 and GSTR-3B bucketing by rate. |
public/fonts/, the supplied logo and favicon from this folder, and no CDN, tracker or external request of any kind. Open the network tab — it stays empty apart from this file and its own assets.
MageTech