- ✅ Supabase project setup
- ✅ Next.js app deployed on Vercel
- ✅ Database already has existing schema running
-
Open Supabase Dashboard
- Go to https://supabase.com/dashboard
- Select your project
-
Navigate to SQL Editor
- Click "SQL Editor" in left sidebar
- Click "New Query"
-
Copy Migration File
- Open
supabase/migration-v2-complete-features.sql - Copy the ENTIRE file content
- Open
-
Paste and Run
- Paste into Supabase SQL Editor
- Click "Run" button
- Wait for completion (should take 5-10 seconds)
-
Verify Success
- No errors should appear
- Check "Table Editor" to see new tables:
- suppliers
- purchases
- purchase_items
- restaurant_tables
- tax_rates
# If you have Supabase CLI installed
supabase db push
# Or apply specific migration
supabase db resetYou need to run this ONCE per shop after migration.
- Go to your app (localhost or production)
- Login as shop owner
- Open browser DevTools (F12)
- Go to Console tab
- Run:
// Replace 'your-shop-id' with your actual shop ID
fetch('/api/init-gst', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ shopId: 'your-shop-id' })
})Add a button in Settings that calls:
import { initializeDefaultGSTRates } from '@/app/actions/tax-rates'
async function handleInitGST() {
if (!shop) return
const { error } = await initializeDefaultGSTRates(shop.id)
if (error) {
toast.error('Failed to initialize GST rates')
} else {
toast.success('GST rates initialized successfully!')
}
}✅ GST 0% (Tax Exempt)
✅ GST 5% (Essential goods)
✅ GST 12% (Standard rate)
✅ GST 18% (Most common) ⭐ DEFAULT
✅ GST 28% (Luxury goods)
// In any page, add temporarily:
import { getTaxRates } from '@/app/actions/tax-rates'
useEffect(() => {
testBackend()
}, [])
async function testBackend() {
const { data, error } = await getTaxRates(shopId)
console.log('Tax Rates:', data)
console.log('Error:', error)
}Expected output:
Tax Rates: [
{ name: 'GST 0%', rate: 0, cgst: 0, sgst: 0 },
{ name: 'GST 5%', rate: 5, cgst: 2.5, sgst: 2.5 },
{ name: 'GST 12%', rate: 12, cgst: 6, sgst: 6 },
{ name: 'GST 18%', rate: 18, cgst: 9, sgst: 9, is_default: true },
{ name: 'GST 28%', rate: 28, cgst: 14, sgst: 14 }
]import { createSupplier } from '@/app/actions/suppliers'
const testSupplier = await createSupplier(shopId, {
name: 'Test Supplier',
company_name: 'Test Company Ltd',
phone: '9876543210',
email: 'test@supplier.com',
gst_number: '29ABCDE1234F1Z5'
})
console.log('Supplier created:', testSupplier)- Create a test purchase order
- Add a product
- Mark status as "received"
- Check product stock quantity increased
# Commit all changes
git add .
git commit -m "feat: Add Purchase Management, GST System, Restaurant Mode"
git push origin mainVercel will automatically deploy.
# Build locally first to check
npm run build
# If successful, push to Vercel
vercel --prodGo to your live app and verify:
- Login works
- Dashboard loads
- No console errors
- Existing features work (POS, Inventory, Sales)
In Supabase Dashboard → Table Editor:
-
supplierstable exists -
purchasestable exists -
purchase_itemstable exists -
restaurant_tablestable exists -
tax_ratestable exists and has 5 default rates
In Table Editor:
- Click on any new table
- Go to "Policies" tab
- Should see policies like "Users can view shop suppliers"
From browser console or test page:
// Test fetching suppliers
const suppliers = await fetch('/api/test-suppliers').then(r => r.json())
// Should return empty array or error (if not initialized)
console.log(suppliers)✅ Migration ran without errors
✅ New tables visible in Supabase
✅ GST rates initialized (5 rates exist)
✅ No errors in browser console
✅ Existing features still work
✅ Code deployed to Vercel
Solution: Tables might partially exist. Either:
- Drop conflicting tables manually
- Or modify migration to use
CREATE TABLE IF NOT EXISTS
Already handled in our migration with IF NOT EXISTS.
Cause: User not authenticated or doesn't have shop access
Solution:
- Ensure user is logged in
- Check
user_rolestable has entry for user - Verify
shop_idmatches
Cause: Not initialized
Solution:
await initializeDefaultGSTRates(shopId)Cause: Trigger might not have run
Solution:
- Check trigger exists:
SELECT * FROM pg_trigger WHERE tgname = 'trigger_update_stock_on_purchase';
- Check
inventory_logstable for entries - Verify purchase status is exactly "received"
Cause: Function not created
Solution: Re-run the migration or manually create function:
-- Copy function definition from migration file-
Check Logs:
- Supabase: Database → Logs
- Vercel: Deployment → Logs
- Browser: DevTools Console
-
Common Issues:
- Authentication: Check Supabase Auth tab
- Database: Check Table Editor
- RLS: Check Policies tab per table
-
Verify Data Flow:
User Login → Shop Loaded → Actions Called → Database Queried → RLS Checked → Data Returned
Run this in browser console after deployment:
async function verifyBackend() {
console.log('🔍 Verifying backend...')
// Check session
const session = await fetch('/api/auth/session').then(r => r.json())
console.log('✅ Session:', session ? 'Active' : '❌ None')
// Check shop
const shop = localStorage.getItem('shop-storage')
console.log('✅ Shop:', shop ? JSON.parse(shop) : '❌ None')
// Check tax rates (will fail if not initialized)
try {
const rates = await getTaxRates(shopId)
console.log('✅ Tax Rates:', rates.data?.length || 0, 'rates found')
} catch (e) {
console.log('❌ Tax Rates Error:', e.message)
}
console.log('✅ Backend verification complete!')
}
verifyBackend()Expected output:
🔍 Verifying backend...
✅ Session: Active
✅ Shop: {id: "...", name: "..."}
✅ Tax Rates: 5 rates found
✅ Backend verification complete!
If all checks pass, your backend is production-ready!
Next: Build UI components for the new features.
Start with: Updating POS to include GST calculator (easiest & most visible).
Quick Links: