Garage Door OS Docs
Price Book

Price Book Auto Cost Calculation

How component costs roll up into price book item pricing automatically.
6 min read

Price Book Auto Cost Calculation from Pending Components

Summary

Enhancement: Added automatic cost calculation for pending inventory components when creating a new price book item. The cost field now updates in real-time as components are added, matching the behavior when editing existing items.

Problem

When adding inventory components during price book item creation (new feature), the cost and unit price fields were not automatically calculated from the component costs. This was inconsistent with the behavior when editing existing items.

Solution

Implemented automatic cost calculation that:
  1. Calculates total cost from all pending components
  2. Updates the cost field automatically in the Basic Information tab
  3. Auto-calculates unit price if markup is set
  4. Displays visual feedback showing the cost is from components
  5. Disables manual cost editing when components are present

Changes Made

1. Added Cost Calculation Logic

Calculate Total Cost from Pending Components

// Calculate total cost from pending components
const pendingComponentsTotalCost = useMemo(() => {
  return pendingComponents.reduce((total, component) => {
    const unitCost = component.unitCost || 0
    const quantity = component.quantity || 1
    return total + (unitCost * quantity)
  }, 0)
}, [pendingComponents])
Features:
  • Uses useMemo for performance optimization
  • Recalculates whenever components or quantities change
  • Sums up: (unit cost Ɨ quantity) for each component

Auto-Update Form Fields

// Update form cost field when pending components change
useEffect(() => {
  if (!editingItem && pendingComponents.length > 0) {
    form.setFieldsValue({ cost: pendingComponentsTotalCost })
    // Auto-calculate unit price if markup is set
    const markup = form.getFieldValue('markup')
    if (markup && markup > 0) {
      const calculatedPrice = pendingComponentsTotalCost * (1 + markup / 100)
      form.setFieldsValue({ unitPrice: calculatedPrice })
    }
  }
}, [pendingComponentsTotalCost, pendingComponents.length, form, editingItem])
Features:
  • Automatically updates cost field when components change
  • Automatically calculates unitPrice if markup is set
  • Only applies to new items (not editing existing items)

2. Visual Cost Summary in Components Tab

Added a green summary card showing:
  • Total Cost - Large, prominent display with $ formatting
  • Component Count - Number of selected components
  • Info Message - Explains cost will auto-update in Basic Information tab
<Card size="small" style={{ marginBottom: 16, backgroundColor: '#f6ffed', borderColor: '#b7eb8f' }}>
  <Row gutter={16}>
    <Col span={6}>
      <Typography.Text type="secondary">Total Cost</Typography.Text>
      <Typography.Text strong style={{ fontSize: 24, color: '#52c41a' }}>
        ${pendingComponentsTotalCost.toFixed(2)}
      </Typography.Text>
    </Col>
    <Col span={6}>
      <Typography.Text type="secondary">Components</Typography.Text>
      <Typography.Text strong style={{ fontSize: 24 }}>
        {pendingComponents.length}
      </Typography.Text>
    </Col>
    <Col span={12}>
      <InboxOutlined style={{ marginRight: 8, color: '#52c41a', fontSize: 20 }} />
      <Typography.Text type="secondary">
        Cost will be automatically calculated...
      </Typography.Text>
    </Col>
  </Row>
</Card>

3. Enhanced Cost Field in Basic Information Tab

Before: Cost field was always editable
After: Cost field is disabled and auto-populated when components exist
<Form.Item name="cost" label="Cost">
  <InputNumber
    min={0}
    precision={2}
    style={{ width: '100%' }}
    placeholder="0.00"
    addonBefore="
quot; disabled={hasComponentCost} value={hasComponentCost ? componentCost : getFieldValue('cost')} onChange={(value) => { if (!hasComponentCost) { form.setFieldValue('cost', value) } }} /> {(calculatedCost > 0 || pendingComponentsTotalCost > 0) && ( <Alert message={`Cost auto-calculated from ${calculatedCost > 0 ? 'saved' : 'pending'} components`} type="success" showIcon /> )} </Form.Item>
Features:
  • Shows green success alert when cost is from components
  • Differentiates between "saved" and "pending" components
  • Field is disabled to prevent manual override
  • Automatically displays calculated cost

4. Enhanced Unit Price Feedback

Updated the unit price alert to show:
  • Cost source (component cost vs manual cost)
  • Markup percentage
  • Calculation formula
<Alert
  message={`Price calculated from ${hasComponentCost ? 'component cost' : 'cost'} + ${markup}% markup`}
  type="success"
  showIcon
  style={{ marginTop: 4, fontSize: 11 }}
/>

User Experience

Workflow

  1. Create new price book item
  2. Go to "Inventory Components" tab
  3. Click "Add Components"
  4. Select inventory items with quantities
  5. See cost summary immediately in green card
  6. Return to "Basic Information" tab
  7. Cost field is auto-populated and disabled
  8. If markup is set, unit price auto-calculates
  9. Visual alerts show what's being calculated

Visual Feedback

In Inventory Components Tab:

  • 🟢 Green summary card with total cost
  • šŸ“Š Real-time component count
  • šŸ’” Info message explaining auto-calculation

In Basic Information Tab:

  • šŸ”’ Disabled cost field (can't manually edit)
  • āœ… Green success alert: "Cost auto-calculated from pending components"
  • āœ… Price alert: "Price calculated from component cost + X% markup"

Benefits

  1. ⚔ Real-time calculation - See costs update as you add components
  2. šŸ”¢ Accurate pricing - No manual calculation errors
  3. šŸ“Š Visual clarity - Clear indicators of where costs come from
  4. šŸ”„ Consistent behavior - Matches editing existing items
  5. šŸ›”ļø Prevents errors - Can't accidentally override calculated costs
  6. šŸ’° Automatic markup - Unit price auto-calculates with markup

Examples

Example 1: Simple Component Addition

  1. Add 3 screws @ $0.50 each = $1.50
  2. Add 1 bracket @ $5.00 = $5.00
  3. Total Cost: $6.50 (automatically shown)
  4. Set markup to 50%
  5. Unit Price: $9.75 (automatically calculated)

Example 2: Editing Quantities

  1. Add 10 units @ $2.00 each = $20.00
  2. Change quantity to 15
  3. Cost updates to $30.00 immediately
  4. If markup is 100%, price updates to $60.00

Example 3: Multiple Components

  1. Component A: 5 Ɨ $1.00 = $5.00
  2. Component B: 2 Ɨ $10.00 = $20.00
  3. Component C: 1 Ɨ $15.00 = $15.00
  4. Total: $40.00 (shown in green card)
  5. With 25% markup → Price: $50.00

Edge Cases Handled

āœ… No components - Cost field is editable
āœ… Components removed - Cost recalculates
āœ… Quantity changed - Cost updates immediately
āœ… Zero cost items - Handled gracefully
āœ… Editing existing items - Uses saved components
āœ… Switching tabs - Cost persists correctly
āœ… Modal cancelled - Pending components cleared

Files Modified

apps/web/src/pages/priceBook/PriceBook.tsx
  • Added pendingComponentsTotalCost calculation (useMemo)
  • Added useEffect to auto-update form fields
  • Enhanced cost field with disabled state and alerts
  • Enhanced unit price alerts with better messaging
  • Added cost summary card in components tab

Testing Checklist

  • Add components and verify cost auto-calculates
  • Change component quantities and verify cost updates
  • Set markup and verify unit price auto-calculates
  • Remove components and verify cost clears
  • Verify cost field is disabled when components exist
  • Verify cost field is editable when no components
  • Check green alerts display correctly
  • Verify cost summary card shows correct totals
  • Test with zero-cost components
  • Test with decimal quantities (e.g., 0.5)
  • Verify editing existing items still works

Future Enhancements

  • Add profit margin calculator
  • Show total cost vs selling price comparison
  • Add suggested pricing based on market rates
  • Batch update markup for multiple items
  • Export cost breakdown report

Created: October 18, 2025
Status: āœ… Complete - Ready for Testing Related: PRICE_BOOK_COMPONENTS_CREATE_FEATURE.md