Mapping DVIR Defects to CMMS Work Orders
A classified defect and a CMMS work-order line item are not the same shape, and the translation between them is where compliance traceability is won or lost. A defect carries a defect_category, a severity_score, and an audit_hash; a work order needs a VMRS code the shop can plan against, a priority the queue can sort on, and a back-reference an auditor can follow. Get the mapping wrong and you either open duplicate work orders on a webhook retry — wasting a mechanic’s bay on a repair that is already done — or you drop the traceability link that ties the repair back to the specific inspection report, which breaks the systematic maintenance record required by 49 CFR § 396.3. This guide gives the concrete, field-level mapping from one classified defect to one CMMS work-order line item.
It is the implementation detail beneath CMMS Work Order Synchronization, which owns the bidirectional sync loop, and it sits in the Telematics, ELD & Maintenance Platform Integration section that defines the canonical DvirComplianceEvent. The VMRS translation reuses the taxonomy from Mapping VMRS Codes to DVIR Defect Taxonomy, and the priority derivation reuses the severity bands from the Severity Scoring Algorithms for DVIR Defects engine.
Prerequisites
Anchor link to "Prerequisites"- Python 3.10+ — the code uses
match/case,X | Yunions, anddict[...]generics. - Pydantic 2.x — the
WorkOrdermodel from the parent guide, validated on the way out. - A VMRS lookup table — a mapping from your internal
defect_categoryvalues to VMRS system-assembly-component codes, sourced from the taxonomy page above. - A durable store with a unique constraint on
(dvir_id, defect_id)— the enforcement point for idempotent create. Application-side checks alone will not survive two racing consumers. - The inbound
DvirComplianceEvent— already scored, routed, and hashed upstream.
Step-by-Step Implementation
Anchor link to "Step-by-Step Implementation"The mapping is a pure function from one defect to one work-order line item, followed by an idempotent create. Keeping the translation pure means the same defect always yields the same work order, which is what makes retries safe.
Step 1 — Translate defect_category to a VMRS code
Anchor link to "Step 1 — Translate defect_category to a VMRS code"VMRS (the Vehicle Maintenance Reporting Standards) is the taxonomy a shop plans and reports against, so the work order must carry a VMRS code, not your internal category string. Look it up from a table, and treat an unknown category as an error to be quarantined, never as a silent default:
# VMRS system-assembly-component codes keyed by internal defect_category.
# Sourced from the DVIR defect taxonomy; keep this table version-controlled.
VMRS_BY_CATEGORY: dict[str, str] = {
"brake_lining_wear": "013-001-002", # Brakes / drum & rotor / lining
"tire_tread_depth": "017-002-001", # Tires / tread / depth
"steering_play": "016-003-004", # Steering / gear / linkage
"lamp_inoperative": "034-001-001", # Lighting / headlamp / bulb
"coupling_defect": "015-001-003", # Frame & coupling / fifth wheel
}
UNKNOWN_VMRS = "999-000-000" # sentinel; routes the work order to manual triage
def resolve_vmrs(defect_category: str) -> tuple[str, bool]:
"""Return (vmrs_code, is_known). An unknown category is flagged, not
silently defaulted, so it cannot masquerade as a mapped repair."""
code = VMRS_BY_CATEGORY.get(defect_category)
if code is None:
return UNKNOWN_VMRS, False
return code, True
Step 2 — Derive priority from the severity band
Anchor link to "Step 2 — Derive priority from the severity band"Priority is a direct function of the severity_score on the compliance event, using the same bands as every other page in the pipeline. Do not re-score here; read the band and map it:
def priority_from_severity(severity_score: int, compliance_action: str) -> str:
"""Map the 0-100 severity band to a work-order priority.
0-34 minor -> scheduled, 35-69 major -> urgent, 70-100 critical -> oos.
Any OOS_HOLD action forces oos regardless of the numeric score, because a
DOT_OOS_CRITERIA defect has an immovable critical floor (49 CFR 396.9)."""
if compliance_action == "OOS_HOLD" or severity_score >= 70:
return "oos"
if severity_score >= 35:
return "urgent"
return "scheduled"
Step 3 — Attach the audit_hash for traceability
Anchor link to "Step 3 — Attach the audit_hash for traceability"The work order must carry the event’s audit_hash so an auditor can follow the repair back to the exact inspection payload that produced it. This is the link that satisfies the § 396.3 systematic-record requirement — a work order with no back-reference to its DVIR is not a defensible maintenance record:
from datetime import datetime, timezone
from pydantic import BaseModel, Field
class WorkOrder(BaseModel):
work_order_id: str
dvir_id: str
defect_id: str
vmrs_code: str
priority: str = Field(pattern=r"^(oos|urgent|scheduled)$")
status: str = "open"
opened_at: datetime
closed_at: datetime | None = None
audit_hash: str # SHA-256 carried from the DvirComplianceEvent for traceability
def build_work_order(event: dict, defect: dict) -> WorkOrder:
"""Map one classified defect on a DvirComplianceEvent to one work order.
Deterministic: the same (event, defect) always yields the same row."""
vmrs_code, _known = resolve_vmrs(defect["defect_category"])
return WorkOrder(
# Deterministic id from the idempotency key — see Step 4.
work_order_id=f"wo-{event['dvir_id']}-{defect['defect_id']}",
dvir_id=event["dvir_id"],
defect_id=defect["defect_id"],
vmrs_code=vmrs_code,
priority=priority_from_severity(event["severity_score"], event["compliance_action"]),
opened_at=datetime.now(timezone.utc),
audit_hash=event["audit_hash"],
)
Step 4 — Create idempotently on the (dvir_id, defect_id) key
Anchor link to "Step 4 — Create idempotently on the (dvir_id, defect_id) key"The create must be a no-op when the work order already exists, because the compliance event is delivered at least once. Push the invariant into the database and let the conflict clause absorb the retry:
from sqlalchemy import text
from sqlalchemy.engine import Connection
def create_work_order(conn: Connection, wo: WorkOrder) -> str:
"""Idempotent create keyed on (dvir_id, defect_id). A webhook retry or
event replay returns the existing work_order_id and creates nothing new."""
return conn.execute(
text("""
INSERT INTO work_orders
(work_order_id, dvir_id, defect_id, vmrs_code, priority, status, opened_at, audit_hash)
VALUES
(:work_order_id, :dvir_id, :defect_id, :vmrs_code, :priority, :status, :opened_at, :audit_hash)
ON CONFLICT (dvir_id, defect_id) DO NOTHING
RETURNING work_order_id
"""),
wo.model_dump(mode="json"),
).scalar() or wo.work_order_id
Verification and Testing
Anchor link to "Verification and Testing"Prove two properties: the mapping is deterministic, and a redelivered event creates exactly one work order. The idempotency proof is the one that keeps a mechanic from working a phantom repair.
import pytest
def test_priority_derivation():
assert priority_from_severity(12, "SCHEDULED_PM") == "scheduled"
assert priority_from_severity(50, "REPAIR_QUEUE") == "urgent"
assert priority_from_severity(88, "OOS_HOLD") == "oos"
# OOS_HOLD forces oos even if the numeric score were somehow lower.
assert priority_from_severity(40, "OOS_HOLD") == "oos"
def test_unknown_category_is_flagged_not_defaulted():
code, known = resolve_vmrs("gremlin_in_the_wiring")
assert known is False
assert code == UNKNOWN_VMRS
def test_create_is_idempotent(conn):
event = {"dvir_id": "D-1", "severity_score": 80, "compliance_action": "OOS_HOLD",
"audit_hash": "abc"}
defect = {"defect_id": "F-1", "defect_category": "brake_lining_wear"}
wo = build_work_order(event, defect)
first = create_work_order(conn, wo)
second = create_work_order(conn, wo) # simulated webhook retry
assert first == second
rows = conn.execute(text(
"SELECT count(*) FROM work_orders WHERE dvir_id='D-1' AND defect_id='F-1'"
)).scalar()
assert rows == 1 # exactly one work order despite two create calls
Common Failure Modes and Gotchas
Anchor link to "Common Failure Modes and Gotchas"- Duplicate defects across consecutive daily DVIRs. The same brake-lining defect reported on Monday and again on Tuesday has two different
dvir_idvalues, so the(dvir_id, defect_id)key opens two work orders — correct in principle, but a nuisance for the shop. Detect the repeat by matching open work orders on(vehicle_vin, vmrs_code)with an unresolved status, and link the Tuesday defect to the existing open order instead of opening a second bay, while still recording the second DVIR reference for the audit trail. Never collapse them by reusing thedvir_id— that would corrupt the traceability back to each inspection. - Mapping an unknown defect code. A
defect_categorywith no VMRS entry must route to manual triage with theUNKNOWN_VMRSsentinel, not fall through to a default code. A defaulted code silently mislabels the repair in the shop’s maintenance history and can hide an OOS-class defect inside a benign VMRS bucket. Alert on any work order created with the sentinel and require a human to assign the real code. - Priority collisions in the shop queue. Two defects on the same vehicle can both map to
oos, and a naive queue will order them arbitrarily. Break the tie deterministically — highestseverity_scorefirst, then earliestopened_at— so the queue is reproducible and an auditor sees a stable ordering. Priority-queue mechanics are covered in Priority Queue Design for Repair-Order Dispatch.
Frequently Asked Questions
Anchor link to "Frequently Asked Questions"What VMRS code should an unmapped defect category get?
Route it to manual triage with an explicit sentinel such as 999-000-000 and alert on it. Never assign a real default code, because a defaulted code silently mislabels the repair in the maintenance history and can bury an out-of-service-class defect inside a benign VMRS bucket. A human must assign the correct code before the work order is planned.
How do I stop a webhook retry from opening a duplicate work order?
Make the create idempotent on the (dvir_id, defect_id) key with a database unique constraint and an ON CONFLICT DO NOTHING clause. A redelivered compliance event then returns the existing work_order_id and creates nothing new, so the mechanic never sees a phantom second repair. Application-side deduplication alone is not enough under concurrent consumers.
Why carry the audit_hash onto the work order?
Because the work order must be traceable back to the exact inspection payload that produced it to serve as a systematic maintenance record under 49 CFR § 396.3. The audit_hash is the SHA-256 fingerprint of the source DVIR event; carrying it onto the work order and the later certification gives an auditor an unbroken, tamper-evident link from repair to report.
Related
Anchor link to "Related"- CMMS Work Order Synchronization — the bidirectional sync loop this mapping feeds.
- Mapping VMRS Codes to DVIR Defect Taxonomy — the VMRS code source this translation reads.
- Severity Scoring Algorithms for DVIR Defects — produces the severity band that sets priority.
- Priority Queue Design for Repair-Order Dispatch — resolves priority collisions in the shop queue.
This guide is part of CMMS Work Order Synchronization. Back to the Telematics, ELD & Maintenance Platform Integration section.