Inventory & Ordering
Sign in to view your restaurant inventory.
Select one restaurant or all restaurants.
Inventory permissions are managed separately by restaurant. Payroll and Close Outs will be built next.
Sign in to view your restaurant inventory.
Log in or create an account with your email and password. Registered users can explore all three restaurant workspaces.
Owner tools are reserved for your verified email. These design settings currently affect only this browser; staff-wide cloud settings come with the Supabase migration.
Try “create a quote,” “new invoice,” “add catering booking,” “open CRM,” or “edit menu.” I’ll open the relevant workflow, but won’t save, send, or charge without your confirmation. This is a command helper, not yet a generative AI model.
Quick actions and checklists. Data remains saved in this browser.
Please log in to use Inventory.
';return}try{const r=await fetch(AUTH+'/user',{headers:{apikey:KEY,Authorization:'Bearer '+s.access_token}});if(!r.ok)throw Error('Session expired: log in again');user=await r.json();access=await request('/inventory_access?select=user_id,location_id,role&user_id=eq.'+encodeURIComponent(user.id));if(!access.length){content.innerHTML='Your account is registered, but an owner must assign you to a restaurant.
Your employee ID: '+esc(user.id)+'
| Product | Category | Bottle size | On hand | Par | Cost / bottle | Vendor | Action |
|---|---|---|---|---|---|---|---|
| '+esc(i.name)+' | '+esc(i.category)+' | '+esc(i.size_ml)+' mL | '+round(qty(i))+' bottles | '+round(i.par_units)+' | '+fmt(i.unit_cost)+' | '+esc(i.vendor)+' | '+(canCount()?' ':'')+(canChange()?'':'')+' |
No products yet. Add your first bottle to begin.
')+'Inventory data is shared in Supabase. Purchase orders remain drafts until handled with your supplier; SkyTab sync is not connected.
';content.querySelector('#inv-location').onchange=e=>{current=e.target.value;draw()};content.querySelectorAll('[data-screen]').forEach(b=>b.onclick=()=>{screen=b.dataset.screen;draw()});content.querySelector('#inv-add')?.addEventListener('click',()=>productForm());content.querySelectorAll('[data-count]').forEach(b=>b.onclick=()=>countForm(b.dataset.count));content.querySelectorAll('[data-edit]').forEach(b=>b.onclick=()=>productForm(b.dataset.edit));content.querySelector('#inv-draft')?.addEventListener('click',draftOrder);content.querySelector('#inv-grant')?.addEventListener('click',grantRole)} function countTable(){return 'Count full bottles and partial bottles as decimals (for example, 0.5 for half a bottle). Latest count is used for on-hand totals.
| When | Product | Bottles | Counted by |
|---|---|---|---|
| '+esc(new Date(x.counted_at).toLocaleString())+' | '+esc(items.find(i=>i.id===x.item_id)?.name||'Item')+' | '+esc(x.counted_units)+' | '+esc(x.counted_by?.slice(0,8))+' |
Suggested quantities are par minus latest physical count, rounded up to whole bottles. Always verify with your supplier before submitting.
'+(canChange()?'':'Viewing only: manager or owner approval required to create orders.
')+'| Date | Vendor | Status | Lines |
|---|---|---|---|
| '+esc(new Date(o.created_at).toLocaleDateString())+' | '+esc(o.vendor)+' | '+esc(o.status)+' | '+esc(o.lines?.length||0)+' |
Viewer: read-only · Counter: record counts · Manager: manage products and draft orders · Owner: full access. To authorize a new employee, ask them for their account ID shown on their Inventory page.
'+(role()==='owner'?'':'Only an owner can grant inventory permissions.
')+'| Account | Role |
|---|---|
| '+esc(a.user_id?.slice(0,13))+'… | '+esc(a.role)+' |
Enter full bottles plus fractional bottles: 2.5 means two full bottles and one half bottle.