Customers

Customers gives operators a searchable view of provider customers, customer detail, billing history, and related provider records.

On this page

Where to look

AreaMaintainer reference
Routes
Implementation referencesrc/app/(dashboard)/customers, /customers/[providerCustomerId], /billing/customers
List server code
Implementation referencesrc/features/customers/server/list
Detail server code
Implementation referencesrc/features/customers/server/detail
Billing grouping
Implementation referencesrc/features/customers/server/billing/grouping.ts
Shared
Implementation referencesrc/features/customers/shared
UI
Implementation referencesrc/features/customers/ui/list-page.tsx, detail-page.tsx, people-lists.tsx
Billing databilling_customers, billing_subscriptions, billing_orders, billing_invoices, billing_charges, billing_refunds, billing_disputes
Implementation reference3 areas

These Product code locations explain how the documented behavior is implemented. Expand them when you are ready to customize or maintain this area.

Customer list and detail

Customer pages delegate list projection, filtering, and detail reads to the customers feature.

  • src/app/(dashboard)/customers/page.tsx
  • src/app/(dashboard)/customers/[providerCustomerId]/page.tsx
  • src/features/customers/ui/list-page.tsx
  • src/features/customers/ui/detail-page.tsx

List query pipeline

List helpers parse filters, build projections, and paginate before rendering customer tables.

  • src/features/customers/server/list/page-query.ts
  • src/features/customers/server/list/filters.ts
  • src/features/customers/server/list/sensitive-data.ts

Billing-backed detail

Customer detail uses provider customer ids and billing grouping helpers without treating provider ids as profile ids.

  • src/features/customers/server/detail/customer.ts
  • src/features/customers/server/billing/grouping.ts
  • src/features/customers/shared/provider-customer-id.ts

Reference paths are relative to the Shipflash-Product checkout.

Customer lookup flow

  1. 1

    Parse filters and pagination

    Customer list requests use server-side filters and page queries before UI renders rows.

    Relevant Product code
    • src/features/customers/server/list/filters.ts
    • src/features/customers/server/list/page-query.ts
  2. 2

    Project list rows

    Projection helpers keep list rows compact and prevent detail-only fields from being loaded for every customer.

    Relevant Product code
    • src/features/customers/server/list/sensitive-data.ts
  3. 3

    Resolve provider detail

    Detail pages use provider customer ids to load customer, billing, and related records.

    Relevant Product code
    • src/features/customers/shared/provider-customer-id.ts
    • src/features/customers/server/detail/customer.ts
  4. 4

    Group billing context

    Billing grouping helpers organize subscriptions, invoices, charges, refunds, and disputes for detail UI.

    Relevant Product code
    • src/features/customers/server/billing/grouping.ts

Customer list bounded query

Use this example as a starting point, then adapt it to your product's rules and configuration.

Customer directory reads are permission-gated, bounded in PostgreSQL, and masked according to the active profile's data permissions.

ts
const profile = await getCachedActiveProfile();
if (!profile || !(await canAccessAsync(profile.role, "customerOperations"))) {
  throw new Error("Unauthorized");
}

const [supabase, provider, enabledModels] = await Promise.all([
  getServiceSupabase(),
  getBillingProvider(),
  getEnabledBillingModels(),
]);
const offset = (filters.page - 1) * filters.limit;

const { data, error } = await supabase.rpc("get_customer_directory_page", {
  p_provider: provider,
  p_enabled_models: enabledModels,
  p_query: safeQuery ?? undefined,
  p_population: filters.population,
  p_status: effectiveStatus,
  p_limit: filters.limit,
  p_offset: offset,
});
if (error) throw error;
Source reference
  • src/features/customers/server/list/page-query.ts

Customer view rules

  • Paginate before customer tables grow.
  • Read only fields needed for list pages.
  • Keep provider customer ids separate from internal profile ids.
  • Use explicit sync paths for provider refresh work.