← CMMS on CAP-686: UI sample vs built

CMMS tables

Branch CAP-686 · migration 20261009104038-cmms-tab.js · structure read from a local database with the migration applied, 14 Oct 2026

One migration: 1 new table, columns added to 4 tables, and existing work-order values converted. Everything runs in a single transaction, and the down step reverses all of it, including converting the values back.

1 new tablework_order_activities, the work-order timeline
19 new columns13 on work_orders, 3 on users, 1 on service_contracts, 2 on camp_inventory_items
3 tables usedby CMMS directly: work_orders, work_order_activities, parts_pos (unchanged)
6 functionsrisk-level function and its 5 triggers updated for the Retired status

On this page

Table changes in CAP-686

New created by this migration   Changed columns added or values converted   Unchanged used as before

TableChangeWhat changes
work_order_activitiesNew9 columns. One row per event on a work order: created, assigned, reassigned, stage or status changed, note, escalated, closed, reopened. Rows are deleted with their work order. The analytics role reads it per account only.
work_ordersChanged 13 columns added:
  • Workflow: stage, closed_reason, closed_by, updated_by
  • Asset: asset_name, for a typed-in asset with no inventory link
  • Requester: requested_by_user_id, requested_by_name, requested_by_title, requested_by_email, requested_by_phone
  • SLA: sla_hours, escalated_at, escalation_target
The type default changes from 'Repair' to 'PM'. Existing type and status values are converted to the new sets. type, status and priority now carry comments listing their allowed values.
usersChanged3 columns added: is_technician, technician_title, technician_capacity. Users who already have work orders assigned are set to is_technician = true.
service_contractsChanged1 column added: coverage_source (oem, third_party or self). Empty means OEM vs HTM is worked out from vendor vs manufacturer.
camp_inventory_itemsChanged2 columns added: retired_at, retired_by. The risk-level function and its triggers now return Retired for assets the bulk retire marks in needs_attention, and existing marked assets are recalculated.
parts_posUnchangedUsed as before. vendor_name is still free text.

work_orders Changed

30 columns: 17 from CAP-15 and 13 new. One row per work order, per account. Soft delete. The number is unique per account.

ColumnTypeNullDefaultNotes
idintegernoserialPK
account_idintegernoFK → accounts
inventory_idintegeryesFK → camp_inventory_items (the asset), on delete set null
asset_name newvarchar(255)yesthe asset as typed; the only reference when there is no inventory link
work_order_numbervarchar(64)noWO-{accountId}-00001; unique per account
type changedvarchar(48)no'PM' (was 'Repair')PM, CM, IN, Install, Project, Other
priorityvarchar(24)no'Medium'Urgent, High, Medium, Low
status changedvarchar(24)no'Open'Open, Under Customer, Escalated, Closed (was Open, In Progress, Completed, Cancelled)
stage newvarchar(32)no'Assigned'Assigned, First Touch, Resolution
assignee_user_idintegeryesFK → users (the technician)
opened_attimestamptznonow
due_attimestamptzyes
closed_attimestamptzyes
closed_reason newvarchar(32)yescompleted or cancelled
closed_by newintegeryesFK → users, on delete set null
requested_by_user_id newintegeryesFK → users, on delete set null
requested_by_name newvarchar(150)yes
requested_by_title newvarchar(150)yes
requested_by_email newvarchar(255)yes
requested_by_phone newvarchar(50)yes
sla_hours newintegeryeshours from opened_at until the SLA window closes
escalated_at newtimestamptzyes
escalation_target newvarchar(120)yeswho an escalation goes to, for example “OEM · Level 2 Tech”
descriptiontextyes
notestextyes
created_byintegeryesFK → users
updated_by newintegeryesFK → users, on delete set null
created_attimestamptznonow
updated_attimestamptznonow
deleted_attimestamptzyessoft delete

work_order_activities New

9 columns. Append-only: rows are added, never edited. The drawer shows the newest 200.

ColumnTypeNullDefaultNotes
idbigintnoserialPK
account_idintegernoFK → accounts, on delete cascade
work_order_idintegernoFK → work_orders, on delete cascade
actionvarchar(32)nocreated, assigned, reassigned, stage_changed, status_changed, note, escalated, closed, reopened
from_valuetextyesthe value before
to_valuetextyesthe value after
notetextyesthe note entered with the change
actor_user_idintegeryesFK → users, on delete set null
created_attimestamptznonow

parts_pos Unchanged

19 columns, from CAP-15. One row per purchase order, per account. Soft delete. The number is unique per account.

ColumnTypeNullDefaultNotes
idintegernoserialPK
account_idintegernoFK → accounts
po_numbervarchar(64)noPO-{accountId}-00001; unique per account
part_numbervarchar(128)yes
descriptiontextyes
vendor_namevarchar(255)yesfree text; there is no vendors table
quantityintegerno1
unit_costdecimal(12,2)yes
statusvarchar(24)no'Ordered'Ordered, Backordered, Delivered, Cancelled
ordered_attimestamptznonow
expected_attimestamptzyes
received_attimestamptzyes
linked_inventory_idintegeryesFK → camp_inventory_items, on delete set null
linked_work_order_idintegeryesFK → work_orders, on delete set null; parts in the drawer come from here
notestextyes
created_byintegeryesFK → users
created_attimestamptznonow
updated_attimestamptznonow
deleted_attimestamptzyessoft delete

New columns on other tables

ColumnTypeNullDefaultNotes
users.is_technician newbooleannofalseshows the user in technician pickers and Team Stats
users.technician_title newvarchar(100)yesfor example “Sr. Biomed Tech”; falls back to the job title
users.technician_capacity newsmallintno6open + active work orders that count as a full load; not read by any endpoint yet
service_contracts.coverage_source newvarchar(20)yesoem, third_party, self; empty means derive from vendor vs manufacturer
camp_inventory_items.retired_at newtimestamptzyeswhen the CMMS retire archived the asset
camp_inventory_items.retired_by newintegeryesFK → users, on delete set null

Functions: compute_risk_level_for_row gains a needs_attention argument and returns Retired when it holds the retired mark. The row trigger trg_inv_risk_level_set now also fires when needs_attention changes, and the four cascade triggers (category, contract, model, model EOL) pass the new argument. The matching .sql files in database/triggers-and-functions/functions/ are updated.

Reused tables

CMMS reads these existing tables. CAP-686 doesn’t change them, apart from the columns listed above.

PM and coverage columns on camp_inventory_items

ColumnTypeUsed for
next_service_datedatePM Overdue (before today), within 30 / 60 days
last_service_datedatePM schedule in the drawer
pm_schedulevarchar(150)PM schedule
pm_intervalvarchar(255)PM schedule
pm_statusvarchar(255)PM schedule
pm_sourceenum: file, sticker, selfwhere the PM data came from
pm_vendor_name, pm_phone, pm_emailvarchar(255)PM vendor
pm_notestextPM notes
service_contract_idintegercontract coverage, OEM vs HTM, high-risk (annual cost ÷ purchase price ≥ 40%)
warranty_id, warranty_expiration_dateinteger, datewarranties ending in 90 days
risk_levelvarchar(20)includes the new Retired value
needs_attentionvarchar(200)holds the retired mark the bulk retire sets

service_histories

Service lines imported from a customer’s own CMMS export (CAP-677). One row per activity line; serial number is the join key to inventory.

ColumnTypeNullNotes
idintegernoPK
account_idintegernoFK → accounts
inventory_idintegeryesFK → camp_inventory_items, on delete set null
document_manager_idintegeryesFK → document_manager (the source file)
additional_detailsjsonbyesdefault {}
extracted_datajsonbyes
tagvarchar(255)yes
serial_numbervarchar(255)yes
wo_numbervarchar(255)yesthe customer’s own WO number
wo_request_datetimestamptzyes
service_typevarchar(255)yesCMMS codes, for example PM, CM, IN
statusvarchar(255)yesCMMS codes, for example CL, OP
rankintegeryes
activity_done_datetimestamptzyes
response_codevarchar(255)yes
actionstextyes
failure_codevarchar(255)yes
stat_datetimestamptzyes
created_at, updated_attimestamptzno
deleted_attimestamptzyessoft delete

inventory_service_history

Older per-asset service tickets, from 2024.

ColumnTypeNullNotes
idintegernoPK
account_idintegernoFK → accounts
inventory_idintegernoFK → camp_inventory_items
ticket_numbervarchar(255)yes
service_request_datetimestamptzyes
request_sourcevarchar(255)yes
service_typevarchar(255)yes
statusvarchar(255)yes
item_numbervarchar(255)yes
serial_numbervarchar(255)yes
po_numbervarchar(255)yes
vendor_namevarchar(255)yes
vendor_etatimestamptzyes
service_descriptiontextyes
created_at, updated_attimestamptzno
deleted_attimestamptzyessoft delete

Also read

FromColumnToMeaning
work_ordersaccount_idaccountsthe facility that owns the WO
work_ordersinventory_idcamp_inventory_itemsthe asset (or asset_name when there is none)
work_ordersassignee_user_idusersthe technician
work_ordersrequested_by_user_id, created_by, updated_by, closed_byuserswho asked, created, last changed, closed
work_order_activitieswork_order_idwork_ordersthe WO’s timeline
work_order_activitiesactor_user_iduserswho did it
parts_poslinked_work_order_idwork_ordersparts on a WO
parts_poslinked_inventory_idcamp_inventory_itemsthe asset the part is for
camp_inventory_itemsretired_byuserswho retired the asset
service_histories, inventory_service_historyinventory_idcamp_inventory_itemsimported and older service records