Build a clean first database plan for the current Flutter UI. The app clearly has 3 roles:
- Admin
- Customer
- Provider
The UI also already implies these main modules:
- Auth and profile
- Provider business profile
- Service categories and services
- Booking and schedule
- Offers and promo
- Favorites
- Chat
- Notifications
- Payments / wallet / payouts
- Reviews
- Location for everyone
For a relevant first version, use 14 tables.
Core:
profilescustomer_profilesprovider_profileslocationsservice_categoriesservicesservice_mediaprovider_availabilitybookingsbooking_status_historyoffersfavoritesreviewsnotifications
Phase 2 if needed:
messageswallet_transactionspayoutsadmin_actionspromo_codes
- One Supabase auth user -> one
profilesrow - One
profilesrow -> optional onecustomer_profilesrow - One
profilesrow -> optional oneprovider_profilesrow - One
profilesrow -> manylocations - One
service_categoriesrow -> manyservices - One provider -> many
services - One provider -> many
provider_availability - One customer -> many
bookings - One provider -> many
bookings - One booking -> many
booking_status_history - One service -> many
offers - One customer -> many
favorites - One booking -> one review max
- One user -> many
notifications
Base account table for all roles. Link this with auth.users.id.
Columns:
id uuid primary keyreferences auth user idrole textcheck in (admin,customer,provider)full_name textemail textphone textavatar_url textgender text nullis_active boolean default truecreated_at timestamptz default now()updated_at timestamptz default now()
Customer-specific data.
Columns:
user_id uuid primary keyreferencesprofiles.iddefault_location_id uuid nulldate_of_birth date nullnotes text nullcreated_at timestamptzupdated_at timestamptz
Provider business and verification data from the provider UI.
Columns:
user_id uuid primary keyreferencesprofiles.idbusiness_name textowner_name textbusiness_email textbusiness_phone textbusiness_address textbio textexperience_years int nulltrade_license_number text nullnid_number text nullverification_status textcheck in (pending,verified,rejected,suspended)service_area_text text nullrating_avg numeric(3,2) default 0review_count int default 0joined_at timestamptz default now()updated_at timestamptz
Reusable location table for customer and provider. This is needed because location is visible in multiple screens.
Columns:
id uuid primary keyuser_id uuidreferencesprofiles.idlabel textlikeHome,Office,Businessaddress_line textarea textcity textdistrict text nullpostal_code text nulllatitude numeric nulllongitude numeric nullis_default boolean default falsecreated_at timestamptz default now()
Admin-controlled categories.
Columns:
id uuid primary keyname text uniqueslug text uniqueparent_group texticon_name text nullis_active boolean default truesort_order int default 0created_at timestamptz default now()
Suggested groups from current UI:
Appliance RepairHome MaintenanceCleaning & Pest Control
Provider-published services.
Columns:
id uuid primary keyprovider_id uuidreferencesprovider_profiles.user_idcategory_id uuidreferencesservice_categories.idname textdescription textvariations text nullfaqs text nullduration_text text nullregular_price numeric(10,2)offer_price numeric(10,2) nullcurrency text default 'BDT'is_active boolean default truecreated_at timestamptz default now()updated_at timestamptz
For service images. The UI supports multiple images and a cover image.
Columns:
id uuid primary keyservice_id uuidreferencesservices.idfile_url textis_cover boolean default falsesort_order int default 0created_at timestamptz default now()
Stores provider weekly schedule.
Columns:
id uuid primary keyprovider_id uuidreferencesprovider_profiles.user_idweekday intuse 0-6 or 1-7 consistentlystart_time timeend_time timeis_active boolean default truecreated_at timestamptz default now()
Most important operational table.
Columns:
id uuid primary keybooking_code text uniquecustomer_id uuidreferencescustomer_profiles.user_idprovider_id uuidreferencesprovider_profiles.user_idservice_id uuidreferencesservices.idlocation_id uuidreferenceslocations.idbooking_date datetime_slot_text textscheduled_at timestamptz nullquantity int default 1unit_price numeric(10,2)total_amount numeric(10,2)payment_method textcheck in (cash,online,wallet,offline)payment_status textcheck in (unpaid,paid,refunded,partial)booking_status textcheck in (pending,accepted,in_progress,completed,rejected,cancelled)customer_note text nullprovider_note text nullcreated_at timestamptz default now()updated_at timestamptz
Tracks booking progress timeline.
Columns:
id uuid primary keybooking_id uuidreferencesbookings.idstatus textchanged_by uuidreferencesprofiles.idnote text nullcreated_at timestamptz default now()
Provider offers and admin-visible offers.
Columns:
id uuid primary keyprovider_id uuidreferencesprovider_profiles.user_idservice_id uuidreferencesservices.idtitle text nulldiscount_percent numeric(5,2) nullpromo_code text nullvalid_until dateis_active boolean default truecreated_at timestamptz default now()
Customer saved services.
Columns:
id uuid primary keycustomer_id uuidreferencescustomer_profiles.user_idservice_id uuidreferencesservices.idcreated_at timestamptz default now()
Constraint:
- unique (
customer_id,service_id)
Customer review for a completed booking.
Columns:
id uuid primary keybooking_id uuid uniquereferencesbookings.idcustomer_id uuidreferencescustomer_profiles.user_idprovider_id uuidreferencesprovider_profiles.user_idservice_id uuidreferencesservices.idrating intcheck (ratingbetween 1 and 5)comment text nullcreated_at timestamptz default now()
User-specific notifications for booking, offer, and system alerts.
Columns:
id uuid primary keyuser_id uuidreferencesprofiles.idtype textcheck in (booking,offer,system,promo)title textbody textis_read boolean default falserelated_booking_id uuid nullrelated_service_id uuid nullcreated_at timestamptz default now()
These came directly from the screens and should shape enums, seed data, or admin settings.
admincustomerprovider
pendingacceptedin_progresscompletedrejectedcancelled
unpaidpaidrefundedpartial
bookingoffersystempromo
RecommendedPrice (Low to High)Price (High to Low)Rating (High to Low)
AC ServicingAC RepairRefrigeratorTV RepairMicrowaveWashing MachineWater PurifierPlumberElectricianCarpenterPainterFull HomeSofa CleanBathroomPest ControlCleaningElectronicsElectronics ServiceFan & Light ServiceFridge ServicingPaintingWater Filter ServicingHouse CleaningHome SanitizationLaundry Service
- Use
auth.usersfor authentication. - Keep
profiles.id = auth.users.id. - Add Row Level Security from day 1.
- Customers should only access their own profile, bookings, favorites, reviews, and notifications.
- Providers should only access their own profile, services, schedule, offers, bookings assigned to them, and their reviews summary.
- Admin access should be via role check on
profiles.role = 'admin'.
Build in this order:
profiles,customer_profiles,provider_profiles,locationsservice_categories,services,service_mediaprovider_availabilitybookings,booking_status_historyfavorites,reviews,notificationsoffers- Phase 2 tables for chat, wallet, payout, and admin logs
For your current UI, start with 10 core tables first:
profilescustomer_profilesprovider_profileslocationsservice_categoriesservicesprovider_availabilitybookingsreviewsnotifications
Then add offers, favorites, service_media, and booking_status_history.
This keeps the first Supabase integration manageable while still matching the real app screens.