/login/register → 4-step onboarding wizard/forgot-password via Supabase Auth emailFull access to all features. The dealer is the account owner and has unrestricted access to:
trg_staff_hash_pin triggerstaff_sessions table with SHA-256 hashed tokens/:shopSlug/:branchSlug/staffstaff_portal_context_v2 — resolves shop/branch from URL slugsstaff_login_attempts table tracks failed attemptsEach staff member is assigned to one or more branches via branch_ids UUID[] on the staff_members table. Staff can only see and create data within their assigned branches. The branch context is set on login and cannot be changed without re-authenticating.
Staff permissions are stored as a JSONB object on staff_members.permissions. Each key maps to a module and the value is either "visible" or "hidden".
| Permission Key | Module | Default |
|---|---|---|
dashboard | Dashboard | visible |
billHistory | Bill History | visible |
newBill | Create New Bill | visible |
farmerList | Farmer List | visible |
addFarmer | Add New Farmer | visible |
inventory | Inventory / Stock | visible |
suppliers | Suppliers | hidden |
cashbook | Cashbook | hidden |
expenses | Expenses | hidden |
reports | Reports | hidden |
settings | Settings | hidden |
branches | Branch Management | hidden |
staffManagement | Staff Management | hidden |
transactions | Transaction History | hidden |
admin_sessions table with SHA-256 hashed tokens/admin/loginAdminLayout component, completely isolated from dealer UI| Role | Capabilities |
|---|---|
superadmin | Full platform access — manage all dealers, subscriptions, product catalog, broadcasts, audit logs, admin users |
admin | Manage dealers, subscriptions, support tickets, product catalog |
support | View dealers (read-only), manage support tickets, impersonate dealers (read-only) |
The core workflow. On mobile it's a 3-step wizard; on desktop it's a 2-panel layout. Both converge on the same save logic.
FarmerSelector component shows recent farmers first, with a search field. If the farmer doesn't exist, QuickAddFarmerModal allows inline creation without leaving the bill flow.ProductSelector component (1,519 lines) shows the dealer's product catalog. Search, filter by category. For each product: enter quantity, confirm rate (auto-filled from latest lot), apply per-farmer discount if configured. Products are added to the bill items list. Up to 5 concurrent draft tabs in sessionStorage for switching between partial bills.PaymentStep shows the bill total. Enter payment amount (can be 0 for full credit, partial, or full). Select payment method (cash, UPI, bank transfer, cheque). The ReviewStep shows a summary. Optional: capture signature on canvas.create_bill_v2 RPC. This is an atomic PostgreSQL function that in a single transaction: creates the bill record, inserts bill items, deducts stock from FIFO lots, records payment (if any), allocates payment to the bill, creates cash book entry, updates farmer due balance. On success, the user is shown the bill detail with options to share via WhatsApp or download PDF.| Dimension | Dealer (Owner) | Staff Member | Platform Admin |
|---|---|---|---|
| Auth method | Email + password (Supabase Auth) | 4+ digit PIN (bcrypt) | Email + password (custom) |
| Session storage | JWT (Supabase SDK) | staff_sessions table | admin_sessions table |
| Entry URL | /login | /:shopSlug/:branchSlug/staff | /admin/login |
| Data scope | All own dealer data | Assigned branch(es) only | All dealers (platform-wide) |
| Rate limiting | Supabase default | staff_login_attempts | None |
| Permission model | Full access | 14-key JSONB (client-side) | Role-based (superadmin/admin/support) |
| Can create bills | Yes | Yes (if newBill = visible) | No |
| Can manage staff | Yes | No (unless granted) | No |
| Can view profit | Yes | No | Yes (impersonation) |