Skip to content
Telematics & Integration

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.

  • Python 3.10+ — the code uses match/case, X | Y unions, and dict[...] generics.
  • Pydantic 2.x — the WorkOrder model from the parent guide, validated on the way out.
  • A VMRS lookup table — a mapping from your internal defect_category values 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.

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:

python
# 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:

python
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:

python
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:

python
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

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.

python
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_id values, 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 the dvir_id — that would corrupt the traceability back to each inspection.
  • Mapping an unknown defect code. A defect_category with no VMRS entry must route to manual triage with the UNKNOWN_VMRS sentinel, 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 — highest severity_score first, then earliest opened_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.
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.

This guide is part of CMMS Work Order Synchronization. Back to the Telematics, ELD & Maintenance Platform Integration section.