Skip to content
Telematics & Integration

CMMS Work Order Synchronization

A classified defect is not closed until a mechanic has repaired it and someone has certified that repair — and that certification is a federal obligation, not a workflow nicety. Under 49 CFR § 396.11©(2), a motor carrier must certify that every defect noted on a driver vehicle inspection report which would affect safe operation has been repaired before the vehicle is dispatched again, and under § 396.3 it must keep systematic maintenance records proving it. When your maintenance shop lives in a computerized maintenance management system (CMMS) such as Fleetio, Maintenance Connection, or eMaint, the repair-complete signal is created there — and if that signal never flows back to the compliance system, the loop stays open and the vehicle is dispatched on an uncertified repair. This guide specifies the bidirectional synchronization that turns a classified defect into a CMMS work order and drives the completion back to the certification gate that clears the vehicle.

This section sits inside the Telematics, ELD & Maintenance Platform Integration section, which defines the canonical outbound DvirComplianceEvent that every downstream platform consumes. Severity scoring is produced upstream by the Severity Scoring Algorithms for DVIR Defects engine and the routing decision by Critical vs Non-Critical Routing Logic; this layer takes the resulting event, opens the corresponding work order, and reconciles its status. The field-level translation from a defect to a single work-order line item is covered in depth in Mapping DVIR Defects to CMMS Work Orders; this page defines the schema, the sync algorithm, and the compliance gate those mappings feed.

Bidirectional DVIR-to-CMMS work-order synchronization closing the certification loop A closed loop in two lanes. In the outbound lane, classified DVIR defects enter a work-order mapper that performs an idempotent upsert keyed on the pair of dvir_id and defect_id, then creates or updates a work order in the CMMS such as Fleetio, Maintenance Connection, or eMaint. In the inbound lane, a mechanic marks the repair complete in the CMMS, a completion webhook flows back into a status reconciler, and the reconciler advances the work order to completed and then verified. The verified status feeds a certification gate enforcing 49 CFR 396.11(c)(2); only when every affecting defect on the DVIR is verified does the gate clear the vehicle for dispatch, otherwise it holds the vehicle out of service. OUTBOUND · create work orders Classified DVIR defects DvirComplianceEvent severity_score · action Work-order mapper idempotent upsert key (dvir_id, defect_id) CMMS Fleetio · eMaint · Maintenance Connection status: open INBOUND · completion flows back mechanic marks repair complete Status reconciler completion webhook open→completed→verified Certification gate § 396.11(c)(2) all affecting defects verified? yes Clear for dispatch no Hold out of service

Prerequisites and Environment Setup

Anchor link to "Prerequisites and Environment Setup"

Work-order synchronization is a long-running service, not a batch job: it consumes compliance events, holds open work orders, and reacts to inbound completion webhooks at arbitrary times. Target Python 3.10+ (the code uses X | Y unions, match/case, and list[...] generics) with:

  • Pydantic 2.x — model the WorkOrder contract and validate every inbound CMMS payload before it touches your state.
  • httpx — async HTTP client for the outbound CMMS REST calls, with per-vendor timeouts and retry budgets.
  • A CMMS account with API + webhook access — Fleetio, Maintenance Connection, and eMaint each expose a work-order create/update API and outbound webhooks; the vendor-neutral adapter layer pattern applies here too when you support more than one.
  • A durable store keyed on (dvir_id, defect_id) — Postgres with a unique constraint on that pair is the enforcement point for idempotent upsert; do not rely on application-side deduplication alone.
  • The canonical event contract — the inbound DvirComplianceEvent is defined by the Telematics, ELD & Maintenance Platform Integration section and must already validate against the Standardized DVIR JSON Schema Design contract before it reaches this service.

Never open a work order directly from a raw inspection payload. The event this service consumes has already been scored, routed, and hashed; opening work from unvalidated input lets an OCR artifact or a duplicate submission create phantom repair work that a mechanic will waste a bay on.

Two records govern this loop. The inbound DvirComplianceEvent is the canonical outbound event — reuse it verbatim rather than inventing a local shape. The outbound WorkOrder is the CMMS-facing record this service owns. Keeping the field names identical to the scoring and routing pages lets a single defect be reconstructed end to end during an audit.

Field Type Enumeration / range Compliance tag
work_order_id str CMMS-assigned or client UUID Cross-system correlation key
dvir_id str matches the source DVIR FMCSA_396.11
defect_id str one per classified defect Idempotency key component
vmrs_code str VMRS system-assembly-component Maintenance record taxonomy
priority str (enum) oos, urgent, scheduled Derived from severity band
status str (enum) open, in_progress, completed, verified Certification lifecycle
opened_at datetime (tz-aware) ISO-8601 § 396.3 record anchor
closed_at datetime | None ISO-8601 or null until verified Repair completion timestamp

The status enum is the spine of the certification loop. open and in_progress are shop-side states; completed means the mechanic marked the repair done in the CMMS; verified means your system has reconciled that completion and recorded the carrier certification. Only verified clears the certification gate — a completed work order that has not been verified is not yet a certified repair under § 396.11©(2). Enforce the contract in Pydantic so a malformed CMMS webhook is rejected, not coerced:

python
from datetime import datetime
from enum import Enum

from pydantic import BaseModel, Field


class WorkOrderStatus(str, Enum):
    OPEN = "open"
    IN_PROGRESS = "in_progress"
    COMPLETED = "completed"   # mechanic marked done in the CMMS
    VERIFIED = "verified"     # carrier certification recorded — clears § 396.11(c)(2)


class WorkOrder(BaseModel):
    model_config = {"use_enum_values": True}

    work_order_id: str
    dvir_id: str
    defect_id: str
    vmrs_code: str
    priority: str = Field(pattern=r"^(oos|urgent|scheduled)$")
    status: WorkOrderStatus = WorkOrderStatus.OPEN
    opened_at: datetime
    closed_at: datetime | None = None


class DvirComplianceEvent(BaseModel):
    """Canonical outbound event defined by the section. Reused, never redefined."""
    event_id: str
    dvir_id: str
    vehicle_vin: str
    driver_id: str
    severity_score: int = Field(ge=0, le=100)
    compliance_action: str = Field(pattern=r"^(OOS_HOLD|REPAIR_QUEUE|SCHEDULED_PM)$")
    audit_hash: str        # SHA-256 over canonical JSON
    version: int
    emitted_at: datetime

Synchronization runs as two directional flows sharing one durable state table. The outbound flow creates work; the inbound flow closes it. Both must be idempotent because both are driven by at-least-once delivery — a webhook or event will be redelivered, and a naive handler creates duplicate work orders or double-certifies a repair.

  1. Consume the compliance event. Read the DvirComplianceEvent, verify its audit_hash against the canonical JSON, and reject any event whose hash does not match — a mismatched hash means the payload was altered in flight and must not open work.
  2. Map defect to work order. For each classified defect on the DVIR, translate defect_category to a vmrs_code and derive priority from the severity band. The full field-level mapping is specified in Mapping DVIR Defects to CMMS Work Orders.
  3. Upsert idempotently. Insert the work order keyed on (dvir_id, defect_id). If a row already exists for that pair, update it in place rather than creating a second one. This is what makes a redelivered event a no-op instead of a duplicate repair.
  4. Push to the CMMS. Call the vendor create/update API. Store the CMMS-assigned work_order_id back on the row so later completion webhooks can be correlated.
  5. Reconcile inbound completion. When the CMMS emits a completion webhook, look up the work order by its CMMS id, advance open/in_progresscompleted, and stamp closed_at.
  6. Verify and certify. Record the carrier certification, advance completedverified, and re-evaluate the certification gate for the parent DVIR. Only when every affecting defect is verified may the vehicle be cleared for dispatch.

The upsert is the load-bearing step. Push the uniqueness invariant into the database and let the conflict clause absorb retries:

python
from datetime import datetime, timezone

import httpx
from sqlalchemy import text
from sqlalchemy.engine import Connection

SEVERITY_TO_PRIORITY = {"critical": "oos", "major": "urgent", "minor": "scheduled"}


def band(score: int) -> str:
    # 0-34 minor / 35-69 major / 70-100 critical — identical to the scoring engine.
    return "critical" if score >= 70 else "major" if score >= 35 else "minor"


def upsert_work_order(conn: Connection, wo: WorkOrder) -> str:
    """Insert or update keyed on (dvir_id, defect_id). A redelivered event
    is a no-op, so a webhook retry never opens a duplicate repair order."""
    row = conn.execute(
        text("""
            INSERT INTO work_orders
                (work_order_id, dvir_id, defect_id, vmrs_code, priority, status, opened_at)
            VALUES
                (:work_order_id, :dvir_id, :defect_id, :vmrs_code, :priority, :status, :opened_at)
            ON CONFLICT (dvir_id, defect_id) DO UPDATE
                SET vmrs_code = EXCLUDED.vmrs_code,
                    priority  = EXCLUDED.priority
            RETURNING work_order_id
        """),
        wo.model_dump(mode="json"),
    ).scalar_one()
    return row

Compliance Thresholding and Routing

Anchor link to "Compliance Thresholding and Routing"

The compliance_action on the incoming event already encodes the severity band, and the work order’s priority must mirror it so the shop queues the right work first. The mapping is fixed and matches every other page in this section:

  • OOS_HOLD (severity ≥ 70, or any DOT_OOS_CRITERIA defect): open the work order at priority oos and hold the vehicle out of service. The vehicle may not be dispatched until the corresponding work order reaches verified. This floor is immovable — no CMMS status short of a certified repair clears it, per Out-of-Service Criteria and OOS Hold Triggers.
  • REPAIR_QUEUE (severity 35–69, major): open at priority urgent and route into the regulated 24-hour repair queue. The vehicle may operate only if the defect does not affect safe operation, and the repair must still be certified before the condition is cleared.
  • SCHEDULED_PM (severity 0–34, minor): open at priority scheduled and let Mechanic Assignment & Workload Balancing place it in the preventive-maintenance backlog.

The certification gate is the compliance heart of this loop. Section 396.11©(2) requires the carrier to certify that a defect affecting safe operation has been corrected before the vehicle is operated again, and the next driver’s review under § 396.11©(2)(iii) depends on that certification existing. Model the gate as a pure predicate over the work orders for a DVIR, and refuse to clear the vehicle until every affecting defect is verified:

python
def certification_gate(work_orders: list[WorkOrder]) -> bool:
    """Clear a vehicle only when every OOS/urgent work order for the DVIR is
    verified. A merely 'completed' order is not yet a certified repair under
    49 CFR 396.11(c)(2)."""
    affecting = [wo for wo in work_orders if wo.priority in ("oos", "urgent")]
    return all(wo.status == WorkOrderStatus.VERIFIED for wo in affecting)

The certification event this gate records should reference the mechanic identity and timestamp exactly as Certifying Repairs Under 396.11©(2) specifies, so an auditor can tie the certification to a real person and a real repair.

Production Integration and Platform Synchronization

Anchor link to "Production Integration and Platform Synchronization"

At-least-once delivery in both directions is the defining operational fact. Every design decision below exists to make redelivery safe.

  • Idempotent upsert, enforced in the database. The unique constraint on (dvir_id, defect_id) is the single source of truth. A webhook retry, an event replay, or two consumers racing all converge on the same row. Never generate the work_order_id non-deterministically before checking for an existing row.
  • Status reconciliation, not blind overwrite. Inbound completion webhooks arrive out of order — a completed event can land after a later correction. Advance status only along the legal path open → in_progress → completed → verified; reject a webhook that would move a verified order backward and log it, rather than reopening a certified repair.
  • Conflict handling on divergent state. If the CMMS reports a status that contradicts your record — the shop reopened a work order you had marked verified — do not silently accept it. Route the conflict to a review queue and hold the certification, because a reopened repair means the § 396.11©(2) certification is no longer valid. High-volume conflict bursts belong in a dead-letter queue for controlled replay.
  • Cryptographic traceability. Carry the event’s audit_hash onto the work order and into the certification record, hash-linking each status transition to its predecessor. This gives the same tamper-evident chain the Immutable Audit Trail and WORM Retention guide applies to inspection records, and satisfies the § 396.3 systematic-record requirement.
  • Verify the inbound signature. Treat CMMS webhooks the way you treat any external callback — verify the vendor signature before acting, using the same discipline as Idempotent Webhook Retry and Signature Verification.
  • Idempotent by construction — the (dvir_id, defect_id) unique constraint makes every redelivered event and webhook a no-op; no duplicate work orders.
  • Status transitions are one-directional — advance only along open → in_progress → completed → verified; a backward move is rejected and logged, never applied.
  • The gate demands verified — a completed work order does not clear the certification gate; only a recorded carrier certification does.
  • OOS holds are immovable — a severity-70-and-above defect holds the vehicle until its work order is verified, regardless of CMMS status.
  • Hash the chain — carry audit_hash onto every work order and certification so a repair record is tamper-evident under § 396.3.
  • Signatures verified inbound — reject unsigned or mis-signed CMMS webhooks before they touch state.
  • Conflicts quarantined — divergent CMMS state routes to review and holds certification rather than overwriting.
Why key the work order on both dvir_id and defect_id instead of just the defect?

Because a defect id is only unique within a DVIR, and because idempotency must survive event replay. Keying on the pair (dvir_id, defect_id) guarantees that a redelivered DvirComplianceEvent maps to exactly one work order, so a webhook retry updates the existing row instead of opening a duplicate repair. It also lets an auditor trace a specific work order straight back to the specific defect on the specific inspection report that generated it.

Does a completed work order in the CMMS satisfy 49 CFR 396.11©(2)?

No. A completed status means the mechanic marked the repair done in the CMMS, but § 396.11©(2) requires the carrier to certify that the defect has been corrected. Your system records that certification and advances the work order to verified; only verified clears the certification gate. Treating completed as certification would dispatch a vehicle on an unverified repair.

What happens if the CMMS reopens a work order I already marked verified?

Hold the certification and route the conflict to review. A reopened repair means the condition that justified the § 396.11©(2) certification may not actually be corrected, so the prior certification can no longer be trusted. Do not accept the reopen silently and do not let the vehicle keep operating on the strength of a certification that the shop itself has contradicted.

How do I map a severity score to a work-order priority?

Use the same bands as the rest of the pipeline: 0–34 minor maps to scheduled, 35–69 major maps to urgent, and 70–100 critical (or any DOT_OOS_CRITERIA defect) maps to oos. The priority is derived directly from the severity_score on the compliance event so the shop queue and the compliance state never disagree.

Back to Telematics, ELD & Maintenance Platform Integration.