| Center Name | Network ID | Owner | Location | Contact | Type | Plan | PIN | Actions |
|---|
| Name | Contact | Status | Upline | Referrals | Join Date | Actions |
|---|
| Coach / Owner | Role / PIN | Self Attendance | Client Check-ins | Body Profiles | Leads Added | Active Clients | Actions |
|---|---|---|---|---|---|---|---|
Loading activity data... | |||||||
| Name | Contact | Pack | Start | Days Left | Streak | Refs ⭐ | Status | Actions |
|---|
| Date | Name | Phone | Source / Referred By | Outcome | Amount | Notes | Actions |
|---|
✅ Present Today (0)
⭕ Not Yet (0)
Select a customer above
Their full body composition history will appear here
| Food Name | Type | Goal | Meal | Cal/100g | Protein/100g | Carbs/100g | Fiber/100g | Fat/100g | Actions |
|---|
No active contests. Create one!
No completed contests yet
| Type | Description | Amount(₹) | Category | Date | Actions |
|---|---|---|---|---|---|
💰 No transactions yet. | |||||
Loading forecast…
No coupon data yet.
| Person | Reason | Coupons | Type | Date | Referred Person | Actions |
|---|
| Person | Description | Total | Paid | Balance | Progress | Due Date | Status | Actions |
|---|
| Center | Owner | Days Active | Current Plan | Change Plan | Action |
|---|
Click Refresh to load.
🤖 AI Configuration (Gemini & Groq)
Gemini 2.5 Flash offers a highly stable free tier. Groq models are served instantly but are subject to strict rate limits.
Each customer can also have their own language preference — set it when adding/editing a customer.
Copy all the SQL below → paste in Supabase SQL Editor → click Run
⚠️ Security Note: The RLS policies below use using (true) which allows public access — suitable for single-owner use with a private API key. For multi-user or production deployments, replace with using (auth.uid() is not null) or a stricter role-based policy.
create table if not exists wellness_centers (
id uuid default gen_random_uuid() primary key,
name text not null, location text, contact text,
type text default 'branch', plan_type text default 'free',
created_at timestamptz default now()
);
alter table wellness_centers enable row level security;
create policy "allow all" on wellness_centers for all using (true);
create table if not exists customers (
id uuid default gen_random_uuid() primary key,
name text not null, contact text, pack_type text,
pack_start_date date, pack_end_date date,
wellness_center_id uuid,
created_at timestamptz default now()
);
alter table customers enable row level security;
create policy "allow all" on customers for all using (true);
create table if not exists attendance (
id uuid default gen_random_uuid() primary key,
customer_id uuid, customer_name text,
date date not null default current_date,
status text default 'present', notes text,
created_at timestamptz default now()
);
alter table attendance enable row level security;
create policy "allow all" on attendance for all using (true);
create table if not exists body_composition (
id uuid default gen_random_uuid() primary key,
customer_id uuid, customer_name text,
date date not null default current_date,
weight numeric, muscle_mass numeric,
fat_percentage numeric, bmi numeric, notes text,
created_at timestamptz default now()
);
alter table body_composition enable row level security;
create policy "allow all" on body_composition for all using (true);
create table if not exists finance (
id uuid default gen_random_uuid() primary key,
type text not null, description text,
amount numeric not null, category text,
date date not null default current_date,
created_at timestamptz default now()
);
alter table finance enable row level security;
create policy "allow all" on finance for all using (true);
create table if not exists coaches (
id uuid default gen_random_uuid() primary key,
name text not null, contact text,
wellness_center_id uuid, join_date date,
created_at timestamptz default now()
);
alter table coaches enable row level security;
create policy "allow all" on coaches for all using (true);
create table if not exists inventory_stock_in (
id uuid default gen_random_uuid() primary key,
product_id text not null,
product_name text,
quantity numeric not null default 0,
unit text,
date date not null default current_date,
cost_price numeric,
expiry_date date,
notes text,
created_at timestamptz default now()
);
alter table inventory_stock_in enable row level security;
create policy "allow all" on inventory_stock_in for all using (true);
create table if not exists inventory_stock_out (
id uuid default gen_random_uuid() primary key,
product_id text not null,
product_name text,
quantity numeric not null default 0,
unit text,
date date not null default current_date,
sale_price numeric,
notes text,
created_at timestamptz default now()
);
alter table inventory_stock_out enable row level security;
create policy "allow all" on inventory_stock_out for all using (true);
create table if not exists inventory_daily_usage (
id uuid default gen_random_uuid() primary key,
type text not null default 'summary',
date date not null default current_date,
weight_gain_shakes integer default 0,
weight_loss_shakes integer default 0,
total_customers integer default 0,
product_id text,
product_name text,
quantity numeric,
unit text,
notes text,
created_at timestamptz default now()
);
alter table inventory_daily_usage enable row level security;
create policy "allow all" on inventory_daily_usage for all using (true);
-- ==========================================
-- 👤 CUSTOMER RETENTION COLUMNS
-- ==========================================
ALTER TABLE customers
ADD COLUMN IF NOT EXISTS dob date,
ADD COLUMN IF NOT EXISTS pack_price numeric;
-- ==========================================
-- 📦 INVENTORY RUNNING BALANCE (Auto-maintained by triggers)
-- ==========================================
create table if not exists inventory_stock_balance (
product_id text primary key,
quantity numeric not null default 0,
unit text,
last_updated timestamptz default now()
);
alter table inventory_stock_balance enable row level security;
create policy "allow all" on inventory_stock_balance for all using (true);
create or replace function sync_stock_balance() returns trigger as $$
declare delta numeric; pid text; u text;
begin
if TG_TABLE_NAME = 'inventory_stock_in' then
if TG_OP = 'INSERT' then pid:=NEW.product_id; u:=NEW.unit; delta:=NEW.quantity;
elsif TG_OP = 'DELETE' then pid:=OLD.product_id; u:=OLD.unit; delta:=-OLD.quantity;
elsif TG_OP = 'UPDATE' then pid:=NEW.product_id; u:=NEW.unit; delta:=NEW.quantity-OLD.quantity; end if;
else
if TG_OP = 'INSERT' then pid:=NEW.product_id; u:=NEW.unit; delta:=-NEW.quantity;
elsif TG_OP = 'DELETE' then pid:=OLD.product_id; u:=OLD.unit; delta:=OLD.quantity;
elsif TG_OP = 'UPDATE' then pid:=NEW.product_id; u:=NEW.unit; delta:=OLD.quantity-NEW.quantity; end if;
end if;
insert into inventory_stock_balance(product_id,quantity,unit,last_updated)
values(pid,delta,u,now())
on conflict(product_id) do update
set quantity=inventory_stock_balance.quantity+delta, unit=u, last_updated=now();
return coalesce(NEW,OLD);
end;
$$ language plpgsql;
drop trigger if exists trg_stock_in on inventory_stock_in;
create trigger trg_stock_in after insert or update or delete on inventory_stock_in
for each row execute function sync_stock_balance();
drop trigger if exists trg_stock_out on inventory_stock_out;
create trigger trg_stock_out after insert or update or delete on inventory_stock_out
for each row execute function sync_stock_balance();
-- ==========================================
-- 🎟️ COUPONS (coach_id stores coach OR customer UUID)
-- ==========================================
create table if not exists coupons (
id uuid default gen_random_uuid() primary key,
coach_id uuid not null, quantity integer not null default 1,
type text not null default 'earn', reason text,
referred_person text, date date default current_date,
notes text, wellness_center_id uuid, created_at timestamptz default now()
);
-- NOTE: coach_id is used for both coaches and customers.
-- Coupons are auto-earned: +1 on invite, +3 when referred person takes a pack.
alter table coupons enable row level security;
create policy "allow all" on coupons for all using (true);
-- ==========================================
-- 💳 PAYMENTS
-- ==========================================
create table if not exists payments (
id uuid default gen_random_uuid() primary key,
person_id uuid, person_name text, description text,
total_amount numeric not null, amount_paid numeric not null default 0,
payment_date date default current_date, due_date date,
notes text, center_id uuid, created_at timestamptz default now()
);
alter table payments enable row level security;
create policy "allow all" on payments for all using (true);
-- ==========================================
-- 🎁 PACK HISTORY
-- ==========================================
-- ==========================================
-- 📦 PACK HISTORY TABLE (Run once)
-- ==========================================
create table if not exists pack_history (
id uuid default gen_random_uuid() primary key,
customer_id uuid, customer_name text, pack_type text,
start_date date, price numeric, notes text,
created_at timestamptz default now()
);
alter table pack_history enable row level security;
create policy "allow all" on pack_history for all using (true);
-- ==========================================
-- 🌳 COACH + CUSTOMER NEW COLUMNS
-- ==========================================
ALTER TABLE wellness_centers
ADD COLUMN IF NOT EXISTS owner_id uuid,
ADD COLUMN IF NOT EXISTS plan_type text default 'free';
ALTER TABLE coaches
ADD COLUMN IF NOT EXISTS upline_id uuid,
ADD COLUMN IF NOT EXISTS pack_type text,
ADD COLUMN IF NOT EXISTS pack_start_date date,
ADD COLUMN IF NOT EXISTS pack_price numeric;
ALTER TABLE customers
ADD COLUMN IF NOT EXISTS dob date,
ADD COLUMN IF NOT EXISTS pack_price numeric,
ADD COLUMN IF NOT EXISTS pack_owner_id uuid;
ALTER TABLE attendance
ADD COLUMN IF NOT EXISTS servings integer DEFAULT 1;
-- ==========================================
-- 🚀 UPGRADE V2 SCRIPTS (Run these to fix the "Unable to Save" errors!)
-- ==========================================
ALTER TABLE customers
ADD COLUMN IF NOT EXISTS age integer,
ADD COLUMN IF NOT EXISTS gender text,
ADD COLUMN IF NOT EXISTS height numeric,
ADD COLUMN IF NOT EXISTS address text,
ADD COLUMN IF NOT EXISTS goal text,
ADD COLUMN IF NOT EXISTS join_date date,
ADD COLUMN IF NOT EXISTS referred_by_id uuid,
ADD COLUMN IF NOT EXISTS external_referrer_name text,
ADD COLUMN IF NOT EXISTS external_referrer_phone text,
ADD COLUMN IF NOT EXISTS coach_id uuid;
ALTER TABLE body_composition
ADD COLUMN IF NOT EXISTS height numeric,
ADD COLUMN IF NOT EXISTS age integer,
ADD COLUMN IF NOT EXISTS visceral_fat numeric,
ADD COLUMN IF NOT EXISTS subcutaneous_fat_percentage numeric,
ADD COLUMN IF NOT EXISTS muscle_percentage numeric,
ADD COLUMN IF NOT EXISTS bmr numeric,
ADD COLUMN IF NOT EXISTS body_age integer;
-- ==========================================
-- 📸 TRANSFORMATION PHOTOS (Run once)
-- ==========================================
ALTER TABLE customers
ADD COLUMN IF NOT EXISTS photo_before text,
ADD COLUMN IF NOT EXISTS photo_after text,
ADD COLUMN IF NOT EXISTS preferred_language text;
-- After running above SQL, go to Supabase Dashboard:
-- Storage → New Bucket → Name: customer-photos → Toggle Public ON → Create Bucket
ALTER TABLE coaches
ADD COLUMN IF NOT EXISTS status text default 'Active',
ADD COLUMN IF NOT EXISTS upline text,
ADD COLUMN IF NOT EXISTS notes text,
ADD COLUMN IF NOT EXISTS herbalife_pin text;
-- ==========================================
-- 💪 COACH BODY PROFILE COLUMNS
-- ==========================================
ALTER TABLE coaches
ADD COLUMN IF NOT EXISTS gender text,
ADD COLUMN IF NOT EXISTS dob date,
ADD COLUMN IF NOT EXISTS goal text;
-- ==========================================
-- 🚶 WALK-INS
-- ==========================================
create table if not exists walkins (
id uuid default gen_random_uuid() primary key,
date date not null,
name text not null,
phone text,
pincode text,
source text,
referred_by_id uuid,
referred_by_name text,
outcome text,
amount_received numeric default 0,
product_details text,
notes text,
wellness_center_id uuid references wellness_centers(id),
center_id uuid references wellness_centers(id),
finance_id uuid,
converted boolean default false,
converted_customer_id uuid,
created_at timestamptz default now()
);
alter table walkins enable row level security;
create policy "allow all" on walkins for all using (true);
-- ==========================================
-- 📞 LEADS & FOLLOW-UPS
-- ==========================================
create table if not exists leads (
id uuid default gen_random_uuid() primary key,
center_id uuid references wellness_centers(id),
wellness_center_id uuid references wellness_centers(id),
name text not null,
mobile text,
status text default 'New',
source text,
notes text,
next_followup_date date,
last_called_date date,
created_at timestamptz default now()
);
alter table leads enable row level security;
create policy "allow all" on leads for all using (true);
-- ==========================================
-- 🥗 FOOD AVAILABILITY SETTINGS (Run once)
-- ==========================================
ALTER TABLE wellness_centers
ADD COLUMN IF NOT EXISTS unavailable_foods text;
ALTER TABLE customers
ADD COLUMN IF NOT EXISTS food_override text,
ADD COLUMN IF NOT EXISTS food_restrict text;
-- ==========================================
-- 🥤 SHAKE TRACKING IN ATTENDANCE (Run once)
-- ==========================================
ALTER TABLE attendance
ADD COLUMN IF NOT EXISTS morning_shake text DEFAULT 'center',
ADD COLUMN IF NOT EXISTS postworkout_shake text DEFAULT 'na';
-- ==========================================
-- 🥗 DIET PLAN + MEAL TRACKING (Run once)
-- ==========================================
ALTER TABLE customers
ADD COLUMN IF NOT EXISTS training_type text DEFAULT 'dumbbell',
ADD COLUMN IF NOT EXISTS protein_ratio numeric DEFAULT 2.0,
ADD COLUMN IF NOT EXISTS shake_frequency text DEFAULT 'once',
ADD COLUMN IF NOT EXISTS diet_plan text;
CREATE TABLE IF NOT EXISTS meal_logs (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
customer_id uuid REFERENCES customers(id) ON DELETE CASCADE,
date date NOT NULL,
meal_type text NOT NULL,
completed boolean DEFAULT false,
completed_at timestamptz,
created_at timestamptz DEFAULT now(),
UNIQUE(customer_id, date, meal_type)
);
ALTER TABLE meal_logs ENABLE ROW LEVEL SECURITY;
CREATE POLICY "allow all" ON meal_logs FOR ALL USING (true);
create table if not exists lead_followups (
id uuid default gen_random_uuid() primary key,
lead_id uuid references leads(id) on delete cascade,
called_at date not null,
note text,
next_followup_date date,
created_at timestamptz default now()
);
alter table lead_followups enable row level security;
create policy "allow all" on lead_followups for all using (true);
-- ==========================================
-- 👨🏫 COACH ATTENDANCE (Run once)
-- ==========================================
CREATE TABLE IF NOT EXISTS coach_attendance (
id uuid default gen_random_uuid() primary key,
coach_id uuid references coaches(id) on delete cascade,
date date not null default current_date,
status text default 'present',
wellness_center_id uuid references wellness_centers(id),
created_at timestamptz default now(),
unique(coach_id, date)
);
alter table coach_attendance enable row level security;
create policy "allow all" on coach_attendance for all using (true);
-- ==========================================
-- 📜 DIET PLAN HISTORY (Run once)
-- ==========================================
CREATE TABLE IF NOT EXISTS diet_plan_history (
id uuid default gen_random_uuid() primary key,
customer_id uuid references customers(id) on delete cascade,
plan_json text not null,
generated_at date not null default current_date,
created_at timestamptz default now()
);
alter table diet_plan_history enable row level security;
create policy "allow all" on diet_plan_history for all using (true);
-- ==========================================
-- 📝 CUSTOMER NOTES (Run once)
-- ==========================================
CREATE TABLE IF NOT EXISTS customer_notes (
id uuid default gen_random_uuid() primary key,
customer_id uuid references customers(id) on delete cascade,
note text not null,
follow_up_date date,
created_at timestamptz default now()
);
alter table customer_notes enable row level security;
create policy "allow all" on customer_notes for all using (true);
-- ==========================================
-- 📢 ANNOUNCEMENTS (Run once)
-- ==========================================
CREATE TABLE IF NOT EXISTS announcements (
id uuid default gen_random_uuid() primary key,
title text not null,
message text not null,
target_center_id uuid references wellness_centers(id),
expires_at date,
created_at timestamptz default now()
);
alter table announcements enable row level security;
create policy "allow all" on announcements for all using (true);
-- ==========================================
-- 🏆 CONTESTS & PARTICIPANTS (BTP Support)
-- ==========================================
CREATE TABLE IF NOT EXISTS contests (
id uuid default gen_random_uuid() primary key,
name text not null,
type text default 'weight_loss',
start_date date not null,
end_date date not null,
duration_days integer default 21,
prize_amount numeric default 0,
entry_fee numeric default 0,
senior_amount numeric default 0,
amount_sent_to_senior boolean default false,
senior_sent_date date,
description text,
status text default 'active',
wellness_center_id uuid references wellness_centers(id),
created_at timestamptz default now()
);
alter table contests enable row level security;
create policy "allow all" on contests for all using (true);
CREATE TABLE IF NOT EXISTS contest_participants (
id uuid default gen_random_uuid() primary key,
contest_id uuid references contests(id) on delete cascade,
customer_id uuid references customers(id) on delete cascade,
customer_name text,
start_weight numeric,
start_fat numeric,
start_muscle numeric,
start_bmi numeric,
current_weight numeric,
current_fat numeric,
current_muscle numeric,
current_bmi numeric,
progress numeric default 0,
fee_paid boolean default false,
video_tracking jsonb default '{}'::jsonb,
category text,
created_at timestamptz default now()
);
alter table contest_participants enable row level security;
create policy "allow all" on contest_participants for all using (true);
-- ==========================================
-- 💳 SAAS PLAN TRACKING (Run once)
-- ==========================================
ALTER TABLE wellness_centers
ADD COLUMN IF NOT EXISTS plan_type text default 'free';
-- plan_type values: 'free' | 'growth' | 'elite' | 'president'
-- Set to 'growth' manually after a center upgrades.
-- ==========================================
-- 🪪 PULSEZEN NETWORK ID + DISTRIBUTOR ID (Run once)
-- ==========================================
ALTER TABLE wellness_centers
ADD COLUMN IF NOT EXISTS network_id text,
ADD COLUMN IF NOT EXISTS distributor_id text;
-- network_id: auto-generated PulseZen identity (e.g. PZ-DH-0001) — set by app on center creation
-- ==========================================
-- 🏢 MULTI-CENTER FINANCE TRACKING (Run if you have 2+ centers)
-- ==========================================
ALTER TABLE finance
ADD COLUMN IF NOT EXISTS wellness_center_id uuid references wellness_centers(id);
-- After this, each finance record can be tagged to a center.
-- Use the "Wellness Center" dropdown in Add Transaction to assign.
ALTER TABLE payments
ADD COLUMN IF NOT EXISTS center_id uuid;
ALTER TABLE coupons
ADD COLUMN IF NOT EXISTS wellness_center_id uuid;
ALTER TABLE leads
ADD COLUMN IF NOT EXISTS center_id uuid,
ADD COLUMN IF NOT EXISTS wellness_center_id uuid;
ALTER TABLE walkins
ADD COLUMN IF NOT EXISTS center_id uuid,
ADD COLUMN IF NOT EXISTS wellness_center_id uuid;
-- ==========================================
-- 📦 MULTI-CENTER INVENTORY TRACKING (Run if you use inventory across 2+ centers)
-- ==========================================
ALTER TABLE inventory_stock_in
ADD COLUMN IF NOT EXISTS wellness_center_id uuid references wellness_centers(id);
ALTER TABLE inventory_stock_out
ADD COLUMN IF NOT EXISTS wellness_center_id uuid references wellness_centers(id);
ALTER TABLE inventory_daily_usage
ADD COLUMN IF NOT EXISTS wellness_center_id uuid references wellness_centers(id);
-- After this, the Inventory app will show a center switcher dropdown.
-- Select a center to view/add stock only for that center.
✅ After running, refresh and all sections will work!