intermediate
work-orders
parts-catalog
labor

Parts and Labor Tracking

Log parts and labor against tasks, roll up to per-vehicle lifetime cost, and feed your monthly P&L

Levy Fleets TeamMay 18, 20266 min read

Parts and Labor Tracking

Knowing what each work order costs is the difference between a fleet that grows profitably and a fleet that bleeds margin into a black hole. Levy Service tracks parts consumption and labor minutes against every task and rolls them up into per-vehicle lifetime cost and per-fleet monthly P&L lines.

The parts catalog

Manage your catalog at /dashboard/parts-catalog. Each row in parts_catalog has:

  • SKU (your internal stock keeping unit)
  • Name (human-readable label)
  • Unit cost (in cents, snapshot at the time of catalog entry)
  • Vehicle models (which models this part fits — for example ["es400a", "es400b"])
  • Stock on hand (count in your warehouse)
  • Reorder threshold (alert when stock drops below)

Catalog rows can be global (Levy-maintained list of standard OKAI/Segway parts) or per-subaccount (your own bespoke parts). Global rows have subaccount_id = NULL and are visible to every fleet. You can override a global SKU by creating a per-subaccount row with the same SKU.

Logging parts against a task

From the operator-app's task detail screen, the tech opens Parts and:

  1. Searches the catalog for the SKU
  2. Sets the quantity used
  3. Taps Add

This writes a task_parts row with unit_cost_cents snapshotted from the catalog at the time of use. The snapshot is important: if the catalog price changes next month, the historical record stays accurate.

task_parts.used_by records which tech consumed the part, and stock_on_hand in parts_catalog decrements automatically. When stock drops below reorder_threshold, the ops_manager gets a Slack notification (if configured).

Logging labor

Labor is logged through task_labor:

  • Minutes — the time spent on this task
  • Hourly rate — defaults to the tech's team_members.hourly_rate_cents, override per-task if needed
  • Total cost — computed as (minutes / 60) * hourly_rate_cents

The operator-app captures labor minutes automatically: the clock starts on start and stops on resolve. Techs can edit the minutes before resolving if the auto-captured time is wrong (for example, they left the task open during a lunch break).

Per-task cost rollup

tasks.total_cost_cents is the sum of every task_parts.quantity * task_parts.unit_cost_cents plus every task_labor.total_cost_cents on the task. The column is kept in sync by a DB trigger that fires on insert/update/delete of task_parts and task_labor.

This shows up on the dashboard side drawer as the Total Cost line and rolls up into the per-vehicle and per-fleet analytics.

Per-vehicle lifetime cost

The vehicle detail page at /dashboard/vehicles/[id] carries a Lifetime Maintenance Cost card that sums every closed task's total_cost_cents against the vehicle. The breakdown shows:

  • Parts vs labor split
  • Top 5 task types by spend
  • Tasks per quarter (trend)
  • Cost per ride (lifetime cost / lifetime rides)

This is the data you use to decide when to retire a vehicle. If cost-per-ride climbs above your replacement ROI threshold, it's time.

Fleet-wide P&L line

The analytics page at /dashboard/tasks/analytics carries a Cost per Vehicle heatmap and a Monthly Maintenance P&L chart. The chart is a stacked bar showing parts cost, internal labor cost, and vendor invoice cost per month. This is the slide you put in your monthly investor update.

Behind the scenes, the analytics endpoint reads from the technician_performance materialized view (refreshed nightly by /api/cron/refresh-tech-performance) plus a direct sum against tasks.total_cost_cents.

Vendor invoices

If a task is outsourced to a vendor via the magic-link portal, the vendor uploads an invoice through POST /api/vendor/[token]/tasks/[id]/invoice. This creates a task_vendor_invoices row and a Stripe Invoice (if STRIPE_SECRET_KEY is configured). The invoice cost rolls into tasks.total_cost_cents just like internal parts and labor.

See Vendor Dispatch for the full flow.

Reorder alerts and stock management

The reorder alert is the only place we automate stock decisions. Levy Service does not yet generate purchase orders or interface with your supplier's system — that's a Phase 5 item on the roadmap. For now, the workflow is:

  1. Stock drops below reorder_threshold
  2. Slack alert fires to the ops_manager
  3. Ops manager places the order with their supplier
  4. When stock arrives, ops manager updates stock_on_hand from the parts catalog page

Data retention

Parts and labor rows are kept indefinitely — they are financial records and feed the lifetime cost view. Do not delete them. If you mis-logged a part, edit the row's quantity to zero rather than deleting.

What good fleets track

The fleets that get profitable maintenance ops have three things in common: a clean catalog of 30-50 SKUs (not 300), techs who log labor every task (no exceptions), and a monthly review of the cost-per-vehicle heatmap to spot the lemons.