Skip to content

Repairs Flow

This page explains how repair pricing tools work: the UI calculators, per-tenant settings, pricing logic, and Supabase tables.


Screens & calculators

Repair pricing lives under the /repairs/* routes.

Key pages (all under src/pages/repairs/):

  • RingSizingUp.tsxRing Sizing Up
  • RingSizingDown.tsxRing Sizing Down
  • SolderChain.tsxSolder Chain
  • SolderBracelet.tsxSolder Bracelet
  • ReplaceClaspChain.tsxReplace Clasp (Chain)
  • TightenStones.tsxTighten Stones
  • ProngRebuild.tsxProng Rebuild
  • RhodiumPlating.tsxRhodium Plating
  • PolishClean.tsxPolish & Clean

Common characteristics:

  • Each page:
    • Uses DashboardLayout as the shell.
    • Renders a Repair Details card with form inputs.
    • Renders a Price Estimate card showing breakdown:
    • Labor cost
    • Material cost
    • Markup
    • Total
    • Minimum price note
    • Uses useRepairSettings() to get the per-tenant repair_settings row for the specific repair_type.
    • Opens RepairSettingsDialog to configure defaults (labor rates, material cost/grams, minimums, etc.).
    • Uses calculateRepairPrice() from src/lib/repair-calculations.ts to compute the quote.

Example: Ring Sizing Up (RingSizingUp.tsx)

  • Inputs:
    • Current ring size
    • Target ring size
    • Metal type (14K/18K/22K gold, platinum, silver)
    • Ring width (mm)
  • Logic:
    • Calls getSetting('ring-sizing-up') + calculateRepairPrice('ring-sizing-up', setting, inputs, enableAdvanced).
    • enableAdvanced is determined by isAdvancedEnabled(setting).
    • Shows breakdown + flags if a minimum price is applied.

Example: Solder Chain (SolderChain.tsx)

  • Inputs:
    • Number of breaks/links
    • Chain type (cable, box, rope, curb, other)
    • Metal type
  • Logic:
    • Calls getSetting('solder-chain') + calculateRepairPrice('solder-chain', ...).
    • Material weight per break is derived from grams_per_break in settings (no manual weight input).

Other calculators follow the same pattern, with specific inputs for prongs, stones, clasp type, polishing type, etc.


Per-tenant repair settings

useRepairSettings

File: src/hooks/useRepairSettings.ts

Responsibilities:

  • Load repair settings for all supported repair_type values for the current tenant.
  • Expose helpers for:
    • getSetting(repairType) – returns the effective RepairSetting (DB row or default).
    • fetchSettings() – refetch settings (used after closing RepairSettingsDialog).
    • loading, error state.
  • Fetch current gold price from gold_prices (most recent price_per_gram) and expose it so material cost can track market prices.

repair_settings table

Migration: supabase/migrations/20250111000000_create_repair_settings.sql

  • Table: repair_settings
  • Per-tenant configuration row per repair type.
  • Key fields (subset):
    • tenant_id (FK) – per-tenant scoping.
    • repair_type – one of:
    • ring-sizing-up
    • ring-sizing-down
    • solder-chain
    • solder-bracelet
    • replace-clasp-chain
    • tighten-stones
    • prong-rebuild
    • rhodium-plating
    • polish-clean
    • Pricing mode:
    • pricing_mode'flat-rate' | 'hourly-rate'.
    • Labor pricing:
    • base_labor_cost, labor_rate_per_hour, estimated_hours.
    • Material pricing:
    • material_cost_per_gram – often tied to gold_prices.price_per_gram.
    • grams_per_size_up, grams_per_break, average_clasp_weight, grams_per_prong.
    • Stone/prong-specific fields:
    • stone_size_small_cost, stone_size_medium_cost, stone_size_large_cost.
    • prong_complexity_*_markup.
    • Polish & clean minimums:
    • polish_item_type_*_minimum for different item types.
    • polish_complexity_*_percent for complexity adjustments.
    • Rhodium plating minimums:
    • rhodium_item_type_*_minimum.
    • Markups & overrides:
    • material_markup_percent, labor_markup_percent.
    • complexity_multiplier.
    • base_price, minimum_price.

Row-level security is enabled on repair_settings so tenants only see their own settings.


Pricing logic

calculateRepairPrice

File: src/lib/repair-calculations.ts

Signature:

calculateRepairPrice(
  repairType: RepairType,
  setting: RepairSetting,
  inputs: CalculationInputs,
  enableAdvanced: boolean
): CalculationBreakdown

Inputs are tailored per repair type:

  • Common fields: currentSize, targetSize, metalType, ringWidth, numberOfBreaks, numberOfStones, numberOfProngs, platingItemType, polishItemType, complexityLevel, etc.

Output (CalculationBreakdown):

  • laborCost
  • materialCost
  • subtotal
  • markup
  • complexityMarkup?
  • itemTypeMinimum?
  • complexityAdjustedMinimum?
  • total
  • minimumApplied

Key behaviors:

  1. Labor cost

    • Flat-rate mode:
    • Uses base_labor_cost as default.
    • Adjusts per repair type:
    • prong-rebuild: (base + complexityMarkupPerProng) * numberOfProngs.
    • tighten-stones: uses stone-size-specific cost per stone.
    • solder-*: scales labor with numberOfBreaks.
    • Hourly-rate mode:
    • Uses labor_rate_per_hour * estimated_hours, then adjusts hours:
    • Ring sizing: adjusts for sizeChange and ringWidth.
    • Tighten stones: adjusts for number/size of stones.
    • Rhodium plating: adjusts for items count and item type.
    • Polish & clean: adjusts per item type.
  2. Material cost

    • Uses material_cost_per_gram from settings.
    • For gold repairs (ring-sizing-*, solder-*, replace-clasp-chain, prong-rebuild):
    • Uses helper getKaratPurity(metalType) to scale cost by karat.
    • Uses settings-based weight calculations:
    • ring-sizing-up: grams_per_size_up * sizeChange, adjusted by ring width.
    • solder-*: grams_per_break * numberOfBreaks.
    • replace-clasp-chain: average_clasp_weight.
    • prong-rebuild: grams_per_prong * numberOfProngs.
    • Applies material_markup_percent when enableAdvanced is true.
  3. Markups & complexity

    • Applies labor_markup_percent when enableAdvanced and appropriate.
    • Applies complexity_multiplier or prong-specific complexity markups.
  4. Minimums & base price

    • For polish-clean:
    • Uses item-type-specific minimums + complexity percentages to compute complexityAdjustedMinimum.
    • For rhodium-plating:
    • Uses item-type-specific minimums.
    • For other types:
    • Uses minimum_price from settings.
    • If base_price is higher than computed total, it wins.
    • Sets minimumApplied = true when a minimum overrides the computed total.

Advanced vs basic mode

isAdvancedEnabled(setting) determines whether material/labor markups and complexity multipliers should be applied. When disabled, pricing stays closer to a simple cost-plus model.


Tables involved

  • repair_settings

    • Per-tenant configuration for all repair calculators.
  • gold_prices

    • Holds historical gold prices (price_per_gram, updated_at).
    • useRepairSettings reads the latest value and integrates it into material_cost_per_gram logic.

Repairs do not mutate core business tables (orders, inventory) directly; they are calculators. The resulting quote is meant to be copied into orders, invoices, or communicated to customers.

Future integration

If you later wire repairs directly into orders or invoices (e.g. "Add to order"), document those flows under Orders and Payments and link back here.


Flow diagram

flowchart LR
  U[User] --> RP["Repairs screen (e.g. Ring Sizing Up)"]
  RP --> SETTINGS[useRepairSettings]
  SETTINGS --> RS[(repair_settings)]
  SETTINGS --> GP[(gold_prices)]
  RP --> CALC[calculateRepairPrice]

  click RP "../architecture/frontend/" "Repairs pages & components"
  click SETTINGS "../architecture/frontend/" "Repair settings hook"
  click RS "../architecture/supabase/" "repair_settings table"
  click GP "../architecture/supabase/" "gold_prices table"

Narrative:

  1. User opens a specific repair calculator under /repairs/*.
  2. useRepairSettings loads tenant-specific settings and gold price.
  3. As the user fills the form, calculateRepairPrice recalculates the quote.
  4. The UI shows labor, material, markup, and total, noting when minimums apply.
  5. The user uses this quote to update an order, invoice, or communicate pricing.