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.tsx– Ring Sizing UpRingSizingDown.tsx– Ring Sizing DownSolderChain.tsx– Solder ChainSolderBracelet.tsx– Solder BraceletReplaceClaspChain.tsx– Replace Clasp (Chain)TightenStones.tsx– Tighten StonesProngRebuild.tsx– Prong RebuildRhodiumPlating.tsx– Rhodium PlatingPolishClean.tsx– Polish & Clean
Common characteristics:
- Each page:
- Uses
DashboardLayoutas 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-tenantrepair_settingsrow for the specificrepair_type. - Opens
RepairSettingsDialogto configure defaults (labor rates, material cost/grams, minimums, etc.). - Uses
calculateRepairPrice()fromsrc/lib/repair-calculations.tsto compute the quote.
- Uses
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). enableAdvancedis determined byisAdvancedEnabled(setting).- Shows breakdown + flags if a minimum price is applied.
- Calls
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_breakin settings (no manual weight input).
- Calls
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_typevalues for the current tenant. - Expose helpers for:
getSetting(repairType)– returns the effectiveRepairSetting(DB row or default).fetchSettings()– refetch settings (used after closingRepairSettingsDialog).loading,errorstate.
- Fetch current gold price from
gold_prices(most recentprice_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-upring-sizing-downsolder-chainsolder-braceletreplace-clasp-chaintighten-stonesprong-rebuildrhodium-platingpolish-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 togold_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_*_minimumfor different item types.polish_complexity_*_percentfor 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):
laborCostmaterialCostsubtotalmarkupcomplexityMarkup?itemTypeMinimum?complexityAdjustedMinimum?totalminimumApplied
Key behaviors:
-
Labor cost
- Flat-rate mode:
- Uses
base_labor_costas default. - Adjusts per repair type:
prong-rebuild:(base + complexityMarkupPerProng) * numberOfProngs.tighten-stones: uses stone-size-specific cost per stone.solder-*: scales labor withnumberOfBreaks.- Hourly-rate mode:
- Uses
labor_rate_per_hour * estimated_hours, then adjusts hours: - Ring sizing: adjusts for
sizeChangeandringWidth. - Tighten stones: adjusts for number/size of stones.
- Rhodium plating: adjusts for items count and item type.
- Polish & clean: adjusts per item type.
-
Material cost
- Uses
material_cost_per_gramfrom 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_percentwhenenableAdvancedis true.
- Uses
-
Markups & complexity
- Applies
labor_markup_percentwhenenableAdvancedand appropriate. - Applies
complexity_multiplieror prong-specific complexity markups.
- Applies
-
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_pricefrom settings. - If
base_priceis higher than computed total, it wins. - Sets
minimumApplied = truewhen a minimum overrides the computed total.
- For
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). useRepairSettingsreads the latest value and integrates it intomaterial_cost_per_gramlogic.
- Holds historical gold prices (
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:
- User opens a specific repair calculator under
/repairs/*. useRepairSettingsloads tenant-specific settings and gold price.- As the user fills the form,
calculateRepairPricerecalculates the quote. - The UI shows labor, material, markup, and total, noting when minimums apply.
- The user uses this quote to update an order, invoice, or communicate pricing.
Related docs¶
- Inventory Flow – stock and product modeling.
- Orders Flow – where repair work may be recorded on jobs.
- Supabase Architecture – repair-related tables.
- Frontend Architecture – route map and page structure.