new-site/scripts/document_gen/templates/dot_da_binder_generator.py
justin 9718ab9ffa DOT D&A binder: editable DOCX output, all 6 forms each full-page, service-aware delivery email
- Rewrite dot_da_binder_generator.py to emit an editable .docx (was reportlab PDF)
  so carriers/counsel can review and adapt the program. ~4000 words, 10 sections.
- Render all six required forms (A-F); previously only A, D, E existed. Each form
  starts on its own page (page break) and fills a page.
- Mode-aware policy text for FMCSA/FRA/PHMSA/FTA/FAA/USCG with correct CFR parts
  and random-testing rates; optional single-state Drug-Free Workplace addendum
  (federal DOT program is nationwide; only the optional DFWP addendum is state-keyed).
- Handler now outputs .docx instead of .pdf.
- job_server instant-delivery: attach DOCX (correct MIME) as well as PDF, and use
  DOT-specific email copy + CTA instead of the FCC/telecom boilerplate.
2026-06-02 21:27:44 -05:00

1218 lines
56 KiB
Python

"""
DOT Drug & Alcohol Compliance Program binder generator.
Produces the instant-delivery **editable DOCX** "binder" that ships when a
customer buys the DOT Drug & Alcohol Compliance Program. The binder is a
complete compliance program a small motor carrier can adopt, customise, and
have a lawyer review/edit, bundling everything needed to run a compliant
program under the applicable DOT testing regulation:
1. How to manage your program (step-by-step instructions)
2. Written drug & alcohol testing policy for employees (mode-specific)
3. When testing is required (the six DOT test scenarios)
4. Random testing program (consortium / pool management)
5. Supervisor reasonable-suspicion training materials + live/online access
6. Violations, SAP access, return-to-duty / follow-up
7. EAP / rehab / treatment resources
8. Recordkeeping instructions + retention schedule
9. All required compliance forms (Forms A-F), each on its own page
10. The regulations (citations + how to read the actual rule text)
(+ optional state Drug-Free Workplace addendum)
Output is **DOCX** so an attorney or the carrier can review and edit it. Each
ready-to-use form starts on its own page (page break before) and the section
that follows begins on a fresh page.
DOT operating administrations (policy variants):
- FMCSA : 49 CFR Part 382 (motor carriers / CDL drivers) <- default
- FRA : 49 CFR Part 219 (railroad / MOW)
- PHMSA : 49 CFR Part 199 (pipeline)
- FTA : 49 CFR Part 655 (transit)
- FAA : 14 CFR Part 120 (aviation)
- USCG : 46 CFR Part 16 (maritime)
Usage:
from scripts.document_gen.templates.dot_da_binder_generator import (
generate_da_binder,
)
docx_path = generate_da_binder(
output_path="/tmp/da_binder.docx",
carrier_name="Acme Trucking LLC",
dot_number="1234567",
mode="fmcsa",
cdl_drivers=4,
der_name="Jane Owner",
provider_name="Performance West Consortium",
)
"""
from __future__ import annotations
import logging
from datetime import datetime
from pathlib import Path
LOG = logging.getLogger("document_gen.da_binder")
try:
from docx import Document
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_BREAK
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.shared import Inches, Pt, RGBColor
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
except ImportError: # pragma: no cover - exercised only when docx missing
Document = None # type: ignore[assignment, misc]
LOG.warning("python-docx not installed — D&A binder generation unavailable")
# ── Palette ────────────────────────────────────────────────────────────────
NAVY = RGBColor(0x0B, 0x1F, 0x3A) if Document else None
BLUE = RGBColor(0x1D, 0x4E, 0xD8) if Document else None
SLATE = RGBColor(0x47, 0x55, 0x69) if Document else None
INK = RGBColor(0x1F, 0x29, 0x37) if Document else None
WHITE = RGBColor(0xFF, 0xFF, 0xFF) if Document else None
NAVY_HEX = "0B1F3A"
LIGHT_HEX = "EEF2F7"
ALT_HEX = "F5F8FC"
# ── Mode metadata ──────────────────────────────────────────────────────────
MODE_META: dict[str, dict] = {
"fmcsa": {
"agency": "Federal Motor Carrier Safety Administration (FMCSA)",
"part": "49 CFR Part 382",
"procedures": "49 CFR Part 40",
"covered": "safety-sensitive employees who operate a commercial motor "
"vehicle (CMV) requiring a commercial driver's license (CDL)",
"function": "operating a commercial motor vehicle requiring a CDL",
"clearinghouse": True,
},
"fra": {
"agency": "Federal Railroad Administration (FRA)",
"part": "49 CFR Part 219",
"procedures": "49 CFR Part 40",
"covered": "employees who perform covered service (train and engine, "
"signal, dispatching, and maintenance-of-way functions)",
"function": "performing FRA-covered service",
"clearinghouse": False,
},
"phmsa": {
"agency": "Pipeline and Hazardous Materials Safety Administration (PHMSA)",
"part": "49 CFR Part 199",
"procedures": "49 CFR Part 40",
"covered": "employees who perform operation, maintenance, or emergency-"
"response functions on a pipeline or LNG facility",
"function": "performing PHMSA-covered pipeline functions",
"clearinghouse": False,
},
"fta": {
"agency": "Federal Transit Administration (FTA)",
"part": "49 CFR Part 655",
"procedures": "49 CFR Part 40",
"covered": "employees who perform safety-sensitive functions for a "
"recipient of FTA funding",
"function": "performing FTA safety-sensitive functions",
"clearinghouse": False,
},
"faa": {
"agency": "Federal Aviation Administration (FAA)",
"part": "14 CFR Part 120",
"procedures": "49 CFR Part 40",
"covered": "employees who perform safety-sensitive aviation functions",
"function": "performing FAA safety-sensitive functions",
"clearinghouse": False,
},
"uscg": {
"agency": "United States Coast Guard (USCG)",
"part": "46 CFR Part 16",
"procedures": "49 CFR Part 40",
"covered": "crewmembers who occupy or fill a position that affects the "
"safe operation of a vessel",
"function": "occupying a safety-sensitive crew position",
"clearinghouse": False,
},
}
_RANDOM_RATES = {
"fmcsa": "50% (controlled substances) and 10% (alcohol)",
"fra": "the FRA-published annual minimum random testing rates",
"phmsa": "50% (controlled substances) of covered employees",
"fta": "50% (controlled substances) and 10% (alcohol)",
"faa": "the FAA-published annual minimum random testing rates",
"uscg": "the USCG annual minimum random testing rate (currently 25%)",
}
# ── Low-level docx helpers ──────────────────────────────────────────────────
def _shade(cell, hex_color: str) -> None:
"""Apply a background fill to a table cell."""
tcPr = cell._tc.get_or_add_tcPr()
shd = OxmlElement("w:shd")
shd.set(qn("w:val"), "clear")
shd.set(qn("w:color"), "auto")
shd.set(qn("w:fill"), hex_color)
tcPr.append(shd)
def _set_cell_text(cell, text, *, bold=False, color=None, size=9, white=False):
cell.text = ""
p = cell.paragraphs[0]
p.paragraph_format.space_after = Pt(2)
p.paragraph_format.space_before = Pt(2)
run = p.add_run(text)
run.bold = bold
run.font.size = Pt(size)
if white:
run.font.color.rgb = WHITE
elif color is not None:
run.font.color.rgb = color
else:
run.font.color.rgb = INK
return p
def _add_runs(p, text):
"""Render very small inline markup: **bold** segments."""
import re
for chunk in re.split(r"(\*\*.+?\*\*)", text):
if not chunk:
continue
if chunk.startswith("**") and chunk.endswith("**"):
r = p.add_run(chunk[2:-2])
r.bold = True
else:
p.add_run(chunk)
class _B:
"""Thin builder around a python-docx Document with the binder's styles."""
def __init__(self, doc, meta, carrier_name):
self.doc = doc
self.meta = meta
self.carrier_name = carrier_name
def h1(self, text):
p = self.doc.add_paragraph()
p.paragraph_format.space_before = Pt(6)
p.paragraph_format.space_after = Pt(10)
p.paragraph_format.keep_with_next = True
r = p.add_run(text)
r.bold = True
r.font.size = Pt(18)
r.font.color.rgb = NAVY
# bottom rule
pPr = p._p.get_or_add_pPr()
pbdr = OxmlElement("w:pBdr")
bottom = OxmlElement("w:bottom")
bottom.set(qn("w:val"), "single")
bottom.set(qn("w:sz"), "6")
bottom.set(qn("w:space"), "4")
bottom.set(qn("w:color"), "CBD5E1")
pbdr.append(bottom)
pPr.append(pbdr)
return p
def h2(self, text):
p = self.doc.add_paragraph()
p.paragraph_format.space_before = Pt(12)
p.paragraph_format.space_after = Pt(5)
p.paragraph_format.keep_with_next = True
r = p.add_run(text)
r.bold = True
r.font.size = Pt(13)
r.font.color.rgb = NAVY
return p
def h3(self, text):
p = self.doc.add_paragraph()
p.paragraph_format.space_before = Pt(9)
p.paragraph_format.space_after = Pt(3)
p.paragraph_format.keep_with_next = True
r = p.add_run(text)
r.bold = True
r.font.size = Pt(11)
r.font.color.rgb = BLUE
return p
def body(self, text, *, italic=False, size=10.5, color=None):
p = self.doc.add_paragraph()
p.paragraph_format.space_after = Pt(6)
_add_runs(p, text)
for r in p.runs:
r.font.size = Pt(size)
r.italic = italic
r.font.color.rgb = color or INK
return p
def small(self, text):
p = self.doc.add_paragraph()
p.paragraph_format.space_after = Pt(4)
r = p.add_run(text)
r.font.size = Pt(8)
r.font.color.rgb = SLATE
return p
def bullets(self, items):
for item in items:
p = self.doc.add_paragraph(style="List Bullet")
p.paragraph_format.space_after = Pt(3)
p.paragraph_format.left_indent = Inches(0.3)
_add_runs(p, item)
for r in p.runs:
r.font.size = Pt(10.5)
r.font.color.rgb = INK
def numbered(self, items):
for item in items:
p = self.doc.add_paragraph(style="List Number")
p.paragraph_format.space_after = Pt(3)
p.paragraph_format.left_indent = Inches(0.35)
_add_runs(p, item)
for r in p.runs:
r.font.size = Pt(10.5)
r.font.color.rgb = INK
def table(self, header, rows, widths, *, alt=True):
t = self.doc.add_table(rows=1, cols=len(header))
t.alignment = WD_TABLE_ALIGNMENT.CENTER
t.style = "Table Grid"
t.autofit = False
for i, w in enumerate(widths):
for cell in t.columns[i].cells:
cell.width = Inches(w)
for i, htext in enumerate(header):
c = t.rows[0].cells[i]
_shade(c, NAVY_HEX)
_set_cell_text(c, htext, bold=True, white=True, size=9.5)
for ri, row in enumerate(rows):
cells = t.add_row().cells
for i, w in enumerate(widths):
cells[i].width = Inches(w)
for i, val in enumerate(row):
bold_first = i == 0 and len(header) == 2
_set_cell_text(cells[i], val, bold=bold_first, size=9)
if alt and ri % 2 == 1:
for c in cells:
_shade(c, ALT_HEX)
self.doc.add_paragraph().paragraph_format.space_after = Pt(2)
return t
def page_break(self):
self.doc.add_page_break()
def spacer(self, pts=8):
p = self.doc.add_paragraph()
p.paragraph_format.space_after = Pt(pts)
return p
def fill_line(self, label, *, gap=6):
"""A labelled fill-in line for forms (underscored to right margin)."""
p = self.doc.add_paragraph()
p.paragraph_format.space_after = Pt(gap)
_add_runs(p, label)
for r in p.runs:
r.font.size = Pt(11)
r.font.color.rgb = INK
return p
def blank_lines(self, n=1, label=""):
for i in range(n):
self.fill_line((label if i == 0 else "") +
" " + "_" * 78, gap=12)
def generate_da_binder(
*,
output_path: str,
carrier_name: str,
dot_number: str = "",
mode: str = "fmcsa",
cdl_drivers: int | str = "",
owner_operators: int | str = "",
der_name: str = "",
der_title: str = "Designated Employer Representative (DER)",
provider_name: str = "Performance West Consortium / C-TPA",
state_dfwp: str = "",
) -> str | None:
"""Render the D&A compliance binder as an editable DOCX. Returns the path."""
if Document is None:
LOG.warning("python-docx not installed — D&A binder generation unavailable")
return None
mode = (mode or "fmcsa").lower().strip()
meta = MODE_META.get(mode, MODE_META["fmcsa"])
random_rate = _RANDOM_RATES.get(mode, _RANDOM_RATES["fmcsa"])
today = datetime.now().strftime("%B %d, %Y")
company = carrier_name or "the Company"
doc = Document()
for section in doc.sections:
section.top_margin = Inches(0.8)
section.bottom_margin = Inches(0.8)
section.left_margin = Inches(0.9)
section.right_margin = Inches(0.9)
# Running header + page-number footer (skip styling complications: simple)
_add_header_footer(doc, meta, carrier_name)
b = _B(doc, meta, carrier_name)
# ── Cover ───────────────────────────────────────────────────────────────
b.spacer(60)
for line in ("DOT Drug & Alcohol", "Compliance Program Binder"):
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
r = p.add_run(line)
r.bold = True
r.font.size = Pt(26)
r.font.color.rgb = NAVY
p.paragraph_format.space_after = Pt(2)
p = doc.add_paragraph()
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
p.paragraph_format.space_before = Pt(10)
r = p.add_run(
f"Prepared under {meta['part']} and the U.S. DOT procedures at "
f"{meta['procedures']}")
r.font.size = Pt(13)
r.font.color.rgb = SLATE
b.spacer(24)
cover_rows = [
["Motor Carrier", carrier_name or ""],
["USDOT Number", str(dot_number) or ""],
["Regulating Agency", meta["agency"]],
["Covered Employees", _covered_count(cdl_drivers, owner_operators)],
["Designated Employer Rep.",
f"{der_name or ''}" + (f"{der_title}" if der_name else "")],
["Testing Program / C-TPA", provider_name],
["Program Effective Date", today],
]
t = doc.add_table(rows=0, cols=2)
t.alignment = WD_TABLE_ALIGNMENT.CENTER
t.style = "Table Grid"
for label, val in cover_rows:
cells = t.add_row().cells
cells[0].width = Inches(2.3)
cells[1].width = Inches(4.2)
_shade(cells[0], LIGHT_HEX)
_set_cell_text(cells[0], label, bold=True, color=NAVY, size=10.5)
_set_cell_text(cells[1], val, size=10.5)
b.spacer(28)
b.small(
"Prepared by Performance West Inc. This binder is a compliance "
"resource and editable template, not legal advice. The motor carrier "
"remains responsible for adopting, customising, implementing, and "
"maintaining its own program. Have counsel review before adoption.")
b.page_break()
# ── Table of contents ───────────────────────────────────────────────────
b.h1("What's Inside This Binder")
b.bullets([
"**Section 1 — How to Manage Your Program.** Step-by-step setup and "
"ongoing operating instructions for the Designated Employer "
"Representative (DER).",
"**Section 2 — Written Testing Policy.** Your company drug & alcohol "
"testing policy to adopt and distribute to every covered employee.",
"**Section 3 — When Testing Is Required.** The six DOT test scenarios "
"and what triggers each one.",
"**Section 4 — Random Testing Program.** How the consortium random "
"pool works and your obligations.",
"**Section 5 — Supervisor Training.** Reasonable-suspicion training "
"materials and how to access live/online training.",
"**Section 6 — Violations, SAP & Return-to-Duty.** What happens after "
"a positive test, and Substance Abuse Professional access.",
"**Section 7 — EAP, Rehab & Treatment Resources.** Employee Assistance "
"Program information and treatment referrals.",
"**Section 8 — Recordkeeping.** What to keep, where, and for how long.",
"**Section 9 — Required Forms (A-F).** Every form you need, ready to "
"use, each on its own page.",
"**Section 10 — The Regulations.** Citations and how to read the actual "
"rule text.",
])
if state_dfwp:
b.body(
f"**Addendum — {state_dfwp} Drug-Free Workplace Program.** "
"State-specific policy supplement that runs alongside your DOT "
"program.")
b.body(
"**How to use this binder.** Sections 1 and 9 are for you (the DER). "
"Section 2 is the policy you adopt and hand to employees. Fill in any "
"blanks (DER name, provider, EAP), sign the policy, collect signed "
"acknowledgments (Form A), and keep everything per Section 8.")
b.page_break()
# ── Section 1 — Manage your program ─────────────────────────────────────
b.h1("Section 1 — How to Manage Your Program")
b.body(
f"As a motor carrier subject to {meta['part']}, you must operate a drug "
f"and alcohol testing program covering every {meta['covered']}. The "
"person who runs the program day-to-day is the **Designated Employer "
"Representative (DER)**. The DER receives test results, schedules tests, "
"and immediately removes employees from safety-sensitive duty when "
"required. Follow these steps.")
b.h3("Initial setup (do once)")
setup = [
"**Name your DER and a backup.** Record names and contact information "
"(this binder lists the primary DER on the cover). The DER must be "
"reachable whenever covered employees are working.",
"**Adopt the written policy** in Section 2. Fill in the blanks, sign "
"it, date it, and keep the signed master copy.",
"**Distribute the policy and educational materials** to every covered "
"employee and collect a signed acknowledgment (Form A). Give a copy to "
"each new hire before they perform safety-sensitive duties.",
"**Join a testing program / consortium (C-TPA).** Your program is "
f"administered through {provider_name}, which manages your random pool, "
"scheduling, the collection site(s), the HHS-certified laboratory, and "
"the Medical Review Officer (MRO).",
"**Train your supervisors** (at least 120 minutes total) before they "
"make any reasonable-suspicion decision (Section 5; record on Form F).",
"**Conduct pre-employment drug tests** with a verified negative result "
"before any new covered employee performs safety-sensitive functions.",
]
if meta.get("clearinghouse"):
setup.append(
"**Register with the FMCSA Clearinghouse** at "
"clearinghouse.fmcsa.dot.gov, designate your C-TPA, and run the "
"required pre-employment full query (with the driver's consent).")
b.numbered(setup)
b.h3("Ongoing operations (every year)")
ongoing = [
"Conduct **random tests** throughout the year at the required minimum "
f"annual rate of {random_rate} of covered positions, spread evenly "
"across the year and kept unannounced (Section 4).",
"Test for **reasonable suspicion** when a trained supervisor observes "
"specific, articulable signs (Section 5; Form D).",
"Conduct **post-accident testing** when DOT criteria are met "
"(Section 3; Form E).",
"Run **return-to-duty and follow-up tests** for any employee who "
"violated the rule and completed the SAP process (Section 6).",
"Keep all **records** for the required retention periods (Section 8).",
"Review and re-date the policy at least annually, and re-distribute it "
"when it changes or when you hire.",
]
if meta.get("clearinghouse"):
ongoing.append(
"Run an **annual FMCSA Clearinghouse limited query** on every CDL "
"driver, and a **pre-employment full query** (with consent) before "
"hiring. **Report** violations, refusals, actual-knowledge "
"findings, negative return-to-duty results, and follow-up "
"completion to the Clearinghouse within the required timeframes.")
b.bullets(ongoing)
b.h3("The DER's quick-reference duties")
b.bullets([
"Receive results from the MRO/C-TPA and act on them the same day.",
"Immediately remove an employee from safety-sensitive duty on a "
"verified positive, a 0.04+ alcohol result, or a refusal.",
"Keep the consortium roster current (add hires, remove departures).",
"Make sure selected employees proceed to collection immediately.",
"Maintain the confidential records file and produce it on audit.",
])
b.page_break()
# ── Section 2 — Written policy ──────────────────────────────────────────
b.h1("Section 2 — Written Drug & Alcohol Testing Policy")
b.body(
f"This is the policy {company} adopts and gives to every covered "
f"employee. It satisfies the written-policy requirement of "
f"{meta['part']} and {meta['procedures']}. Replace any bracketed blanks, "
"then sign and date the adoption block at the end.", italic=True)
b.h3("1. Purpose and Authority")
b.body(
f"{company} (the \"Company\") is committed to a safe, drug- and "
"alcohol-free workplace and to protecting the public, its employees, "
"and its property. This policy implements the requirements of the "
f"{meta['agency']} at {meta['part']} and the U.S. Department of "
f"Transportation testing procedures at {meta['procedures']}. Where this "
"policy conflicts with the DOT regulations, the regulations govern. The "
"Company may also maintain separate, non-DOT workplace rules; this "
"policy governs DOT-required testing only.")
b.h3("2. Who Is Covered")
b.body(
f"This policy applies to every {meta['covered']}, including full-time, "
"part-time, intermittent, temporary, and newly hired employees, and "
"owner-operators operating under the Company's authority. A covered "
f"employee is subject to testing whenever {meta['function']}.")
b.h3("3. Safety-Sensitive Functions")
b.body(
"\"Safety-sensitive function\" includes all on-duty time performing or "
"available to perform the covered function, plus related duties such as "
"waiting to be dispatched, inspecting or servicing equipment, "
"supervising or attending the loading/unloading of a vehicle, and "
"performing required post-accident duties.")
b.h3("4. Prohibited Conduct")
b.body("A covered employee must not:")
b.bullets([
"Report for duty or remain on duty with an alcohol concentration of "
"**0.04 or greater**.",
"Use alcohol while performing safety-sensitive functions, within "
"**4 hours** before performing them, or within **8 hours** after an "
"accident (or until tested, whichever is first).",
"Use any illegal drug, or use a controlled substance, unless the use is "
"consistent with a valid prescription that the prescribing licensed "
"medical practitioner has determined will not adversely affect the "
"employee's ability to safely perform the function.",
"Report for duty or remain on duty when using any substance that the "
"prescribing physician has not authorised as consistent with safe "
"performance.",
"**Refuse to submit** to a required test, adulterate or substitute a "
"specimen, or fail to remain readily available for post-accident "
"testing (a refusal is treated the same as a verified positive).",
"Test positive on, or tamper with, any DOT-required drug or alcohol "
"test.",
])
b.h3("5. Required Tests")
b.body(
"The Company conducts the following DOT tests: **pre-employment, "
"random, reasonable suspicion, post-accident, return-to-duty, and "
"follow-up.** Section 3 explains when each applies.")
b.body(
"Drug tests use the DOT 5-panel and screen for marijuana, cocaine, "
"opioids (including codeine, morphine, heroin, hydrocodone, "
"hydromorphone, oxycodone, and oxymorphone), amphetamines (including "
"methamphetamine, MDMA, and MDA), and phencyclidine (PCP). A certified "
"laboratory analyses the specimen; a **Medical Review Officer (MRO)** "
"reviews and verifies any non-negative result and may contact the "
"employee for a legitimate medical explanation before reporting a "
"verified positive to the Company.")
b.h3("6. Consequences of a Violation")
b.body(
"An employee who has a verified positive test, an alcohol concentration "
"of 0.04 or greater, or who refuses a test is **immediately removed "
"from safety-sensitive duty**. The employee may not return until they "
"complete the DOT return-to-duty process with a qualified Substance "
"Abuse Professional (SAP) and pass a return-to-duty test (Section 6). "
"An employee with an alcohol result of 0.02 to less than 0.04 is "
"removed from safety-sensitive duty until the start of the next "
"regularly scheduled duty period, but at least 24 hours. Additional "
"employment consequences, if any, are governed by separate Company "
"rules and applicable law.")
b.h3("7. Designated Employer Representative")
b.body(
f"The Company's DER is {der_name or '[DER NAME]'}"
f"{(', ' + der_title) if der_name else ''}. The DER receives test "
"results, schedules tests, and removes employees from duty as required. "
"Questions about this policy should be directed to the DER.")
b.h3("8. Confidentiality and Employee Rights")
b.body(
"Test records are kept confidential and released only as authorised by "
f"{meta['procedures']} and {meta['part']} (for example, to the "
"employee, an MRO or SAP, a subsequent employer with the employee's "
"written consent, or as required by law or the DOT). On written request "
"an employee may obtain copies of records relating to the employee's "
"own tests.")
b.h3("9. Employee Assistance")
b.body(
"Information about substance abuse, its effects, the signs and symptoms "
"of a problem, and available treatment and Employee Assistance "
"resources is provided in Section 7 of this binder and is available "
"from the DER.")
b.h3("Policy Adoption")
b.body(
"The Company adopts this Drug & Alcohol Testing Policy as of the date "
"below. The signed original is retained by the DER.")
b.spacer(6)
b.fill_line("Company official (print): ___________________________________"
"__________________")
b.fill_line("Signature: _______________________________________ Title: "
"_______________________")
b.fill_line("Effective date: __________________ USDOT #: "
f"{dot_number or '________________'}")
b.page_break()
# ── Section 3 — When testing is required ───────────────────────────────
b.h1("Section 3 — When Testing Is Required")
b.body(
"DOT testing happens in six situations. The table summarises the "
"triggers; the notes below add the detail your DER needs.")
b.table(
["Test Type", "When It Happens"],
[
["Pre-employment",
"Before a new covered employee first performs safety-sensitive "
"functions. A drug test with a verified negative result is "
"required (and an FMCSA Clearinghouse pre-employment full query "
"for CDL drivers)."],
["Random",
"Unannounced and spread throughout the year, selected by the "
"consortium from the random pool (Section 4)."],
["Reasonable suspicion",
"When a trained supervisor observes specific, articulable, "
"contemporaneous signs of drug or alcohol use (Section 5)."],
["Post-accident",
"After a qualifying accident: a fatality; OR a citation to the "
"driver plus an injury requiring immediate medical treatment away "
"from the scene; OR a citation plus a vehicle towed from the scene "
"due to disabling damage. Alcohol test within 8 hours, drug test "
"within 32 hours."],
["Return-to-duty",
"Before an employee who violated the rule may return to safety-"
"sensitive duty, after completing the SAP process. Conducted under "
"direct observation."],
["Follow-up",
"A SAP-directed schedule of unannounced tests (at least 6 in the "
"first 12 months, for up to 5 years) after return to duty. "
"Conducted under direct observation."],
],
[1.5, 5.0],
)
b.h3("Post-accident testing — decide quickly")
b.body(
"Use Form E (Section 9) at the scene. Test if **any** trigger is met. "
"If a required test cannot be done in time, document why. Do not let a "
"driver who must be tested consume alcohol or leave before the alcohol "
"test, and complete the drug test within 32 hours.")
b.h3("Pre-employment exceptions")
b.body(
"A new hire may be exempt from the pre-employment drug test only if you "
"fully document a valid prior-testing exception (participation in a DOT "
"program in the prior 30 days, a DOT drug test in the prior 6 months or "
"random-pool participation for the prior 12 months, and no knowledge of "
"a prior-employer violation). When in doubt, test.")
b.page_break()
# ── Section 4 — Random testing ─────────────────────────────────────────
b.h1("Section 4 — Random Testing Program")
b.body(
"Random testing is the backbone of your program. The minimum annual "
f"random testing rate is {random_rate} of your average number of "
"covered positions. Because most small carriers cannot meet the spread-"
"and-rate requirements on their own, your covered employees are "
f"enrolled in a random pool managed by {provider_name} (a "
"Consortium/Third-Party Administrator, or C-TPA).")
b.h3("How the random pool works")
b.numbered([
"Every covered employee is placed in the consortium's random pool.",
"Each selection period, the consortium randomly selects names using a "
"scientifically valid method (each employee has an equal chance each "
"time).",
"Selected employees are notified and must proceed **immediately** to "
"the collection site — no advance notice, no delay.",
"Selections are spread reasonably throughout the year so testing is "
"truly unannounced and unpredictable.",
"The consortium tracks the rate and gives you a year-end summary for "
"your records and any DOT audit.",
])
b.h3("Your responsibilities")
b.bullets([
"Keep the consortium's roster of covered employees current — add new "
"hires and remove departures promptly.",
"Send selected employees to testing right away and document that they "
"went (notification time, arrival time, completion).",
"Never select, warn, or 'volunteer' specific people — selection must "
"stay random and confidential until notification.",
"For random alcohol tests, test only just before, during, or just "
"after the employee performs safety-sensitive functions.",
"Keep the consortium's selection and results records (Section 8).",
])
b.page_break()
# ── Section 5 — Supervisor training ────────────────────────────────────
b.h1("Section 5 — Supervisor Reasonable-Suspicion Training")
b.body(
f"{meta['part']} requires that any supervisor who may make a "
"reasonable-suspicion testing decision complete at least **60 minutes "
"of training on the symptoms of alcohol misuse** and at least "
"**60 minutes on the symptoms of controlled-substance use** "
"(120 minutes total). Record each supervisor's training on Form F and "
"keep it on file.")
b.h3("Signs a trained supervisor watches for")
b.bullets([
"**Appearance:** bloodshot or watery eyes, dilated/constricted pupils, "
"flushed face, disheveled clothing, drug paraphernalia.",
"**Behavior:** mood swings, agitation, euphoria, drowsiness, paranoia, "
"unusual or unsafe risk-taking.",
"**Speech:** slurred, rapid, incoherent, or unusually talkative.",
"**Coordination:** unsteady gait, tremors, poor balance, fumbling.",
"**Odor:** alcohol or marijuana odor on breath, body, or clothing.",
"**Performance:** sudden decline, missed deadlines, accidents, near-"
"misses, frequent absences.",
])
b.h3("Making a reasonable-suspicion decision")
b.numbered([
"One trained supervisor's specific, contemporaneous, articulable "
"observations are enough — two supervisors are not required.",
"Document the observations in writing immediately (Form D), signed and "
"dated within 24 hours.",
"For alcohol, make the observations just before, during, or just after "
"the employee performs safety-sensitive functions.",
"Direct the employee to testing and do not let them drive themselves.",
"Remove the employee from safety-sensitive duty pending results.",
])
b.h3("Live / online supervisor training access")
b.body(
"Your program includes access to DOT-compliant supervisor training. To "
"complete the required 120-minute course online (or schedule a live "
"session), contact us and we will send each supervisor an enrollment "
"link and issue a dated completion certificate for your records.")
b.bullets([
"**Email:** compliance@performancewest.com — subject \"Supervisor "
"Training\" with your USDOT number.",
"**What you get:** self-paced online modules, a knowledge check, and a "
"dated certificate of completion to keep on file (record on Form F).",
])
b.page_break()
# ── Section 6 — Violations / SAP ───────────────────────────────────────
b.h1("Section 6 — Violations, SAP & Return-to-Duty")
b.body(
"If a covered employee has a verified positive test, an alcohol "
"concentration of 0.04 or greater, or refuses a test, you must "
"**immediately remove them from safety-sensitive duty**. They cannot "
"return until they complete the DOT return-to-duty process.")
b.h3("The return-to-duty process")
b.numbered([
"**Remove from duty** and give the employee the contact information "
"for at least two DOT-qualified Substance Abuse Professionals (SAPs).",
"**SAP evaluation.** The SAP evaluates the employee and prescribes "
"education and/or treatment.",
"**Treatment / education** is completed as directed by the SAP.",
"**Follow-up evaluation.** The SAP confirms the employee complied and "
"is eligible to return.",
"**Return-to-duty test.** The employee must pass a directly observed "
"return-to-duty test (verified negative drug result, or alcohol below "
"0.02) before resuming duties.",
"**Follow-up testing.** The SAP sets an unannounced follow-up testing "
"schedule — at least 6 directly observed tests in the first 12 months, "
"and the plan may continue for up to 5 years.",
])
b.h3("SAP access")
b.body(
"Your program includes access to a network of DOT-qualified Substance "
"Abuse Professionals. To get a SAP referral for an employee, contact "
"the DER or email compliance@performancewest.com with your USDOT "
"number; we will provide qualified SAP contacts in the employee's area. "
"You can also locate a SAP through the DOT and industry directories in "
"Section 7. The employee generally bears the cost of SAP services and "
"testing; the Company is not required to return any employee to duty or "
"to provide a second chance.")
if meta.get("clearinghouse"):
b.h3("FMCSA Clearinghouse reporting")
b.body(
"Report the violation or refusal, actual-knowledge findings, the "
"negative return-to-duty test, and completion of follow-up testing "
"to the FMCSA Clearinghouse within the required timeframes. A driver "
"with an unresolved Clearinghouse violation is 'prohibited' and may "
"not operate a CMV until the return-to-duty requirements are met "
"and recorded.")
b.page_break()
# ── Section 7 — EAP / rehab ────────────────────────────────────────────
b.h1("Section 7 — EAP, Rehab & Treatment Resources")
b.body(
"DOT rules require that you give covered employees educational "
"materials explaining the requirements of the rule, the employer's "
"policies and procedures, the effects and signs of alcohol and "
"controlled-substance use, and available resources. Distribute the "
"materials below with the policy and keep a record of distribution "
"(Form A).")
b.h3("Effects, signs, and intervention")
b.body(
"Alcohol misuse and controlled-substance use can impair judgment, "
"reaction time, coordination, perception, attention, and decision-"
"making, increasing the risk of crashes, injury, death, regulatory "
"violations, job loss, and health and family harm. Anyone who suspects "
"a problem should report it to the DER. Do not attempt to diagnose "
"impairment; document observed facts and contact the DER, who will "
"decide whether reasonable-suspicion testing applies.")
b.h3("National help lines and directories")
b.bullets([
"**SAMHSA National Helpline:** 1-800-662-HELP (4357) — free, "
"confidential, 24/7 treatment referral and information service.",
"**SAMHSA treatment locator:** findtreatment.gov — searchable "
"directory of treatment facilities by location.",
"**988 Suicide & Crisis Lifeline:** call or text 988.",
"**Alcoholics Anonymous:** aa.org — local meeting finder.",
"**Narcotics Anonymous:** na.org — local meeting finder.",
"**DOT SAP information:** transportation.gov/odapc — Office of Drug & "
"Alcohol Policy and Compliance, including SAP and return-to-duty "
"guidance.",
])
b.h3("Employee Assistance Program (EAP)")
b.body(
"An EAP gives employees confidential access to counseling and referral "
"services. If your company offers an EAP, list its contact information "
"on the acknowledgment you give employees. If you do not have an EAP, "
"the national resources above and a SAP referral satisfy the "
"educational and referral expectations of the rule. We can help you add "
"a low-cost EAP — email compliance@performancewest.com.")
b.page_break()
# ── Section 8 — Recordkeeping ──────────────────────────────────────────
b.h1("Section 8 — Recordkeeping")
b.body(
"Keep your records organised, confidential, and secure; you must "
"produce them in a DOT audit. The DER (or your C-TPA on your behalf) "
f"maintains them. Retention periods under {meta['procedures']} / the "
"mode rule:")
b.table(
["Record", "Keep For"],
[
["Verified positive results; refusals; SAP reports; return-to-duty "
"and follow-up test records; alcohol tests of 0.02+", "5 years"],
["Random selection records and the annual random testing rate "
"calculation", "5 years"],
["Reasonable-suspicion and post-accident test records", "5 years"],
["EBT calibration / collection-site documentation", "5 years"],
["Annual MIS summary (if required of your operation)", "5 years"],
["Negative test results and cancelled tests", "1 year"],
["Supervisor training records (Form F)",
"While employed + as required"],
["Employee policy acknowledgments (Form A)",
"Duration of employment + 1 year"],
],
[4.6, 1.4],
)
b.body(
"Store records so they are confidential and retrievable. Your C-TPA "
"keeps a parallel set of consortium records; request a copy any time.",
italic=True)
b.page_break()
# ── Section 9 — Forms ──────────────────────────────────────────────────
b.h1("Section 9 — Required Compliance Forms")
b.body(
"The forms on the following pages are ready to print and use; each form "
"is on its own page. The federal chain-of-custody form (the CCF) and "
"the DOT Alcohol Testing Form (ATF) are supplied by the collection site "
"and lab at each collection — you do not print those yourself.")
b.bullets([
"**Form A** — Employee Policy Receipt & Acknowledgment.",
"**Form B** — Pre-Employment Consent & Prior-Employer Inquiry.",
"**Form C** — Test Notification / Authorization to Test.",
"**Form D** — Reasonable-Suspicion Observation Record.",
"**Form E** — Post-Accident Testing Decision Worksheet.",
"**Form F** — Supervisor Training Completion Record.",
])
_form_a(b, carrier_name, meta)
_form_b(b, carrier_name, meta)
_form_c(b, carrier_name)
_form_d(b, carrier_name)
_form_e(b, carrier_name)
_form_f(b, carrier_name)
# ── Section 10 — Regulations ───────────────────────────────────────────
b.page_break()
b.h1("Section 10 — The Regulations")
b.body(
"Your program is governed by two rules that work together: the DOT-wide "
f"testing procedures at {meta['procedures']}, and the mode rule at "
f"{meta['part']} from the {meta['agency']}. Read the official, always-"
"current text on the free government sites below.")
reg_items = [
f"**{meta['procedures']} (DOT testing procedures):** "
"ecfr.gov/current/title-49/subtitle-A/part-40",
f"**{meta['part']} (your mode rule):** ecfr.gov — search the part "
"number; this rule defines who is covered and the testing scenarios.",
"**DOT ODAPC (plain-language guidance, forms, brochures):** "
"transportation.gov/odapc",
]
if meta.get("clearinghouse"):
reg_items += [
"**FMCSA Drug & Alcohol Clearinghouse:** clearinghouse.fmcsa.dot.gov",
"**FMCSA testing overview:** fmcsa.dot.gov/regulations/"
"drug-alcohol-testing-program",
]
b.bullets(reg_items)
b.small(
"Regulations change. This binder reflects the rules in effect on "
f"{today}. Always confirm the current rule text on ecfr.gov, and have "
"counsel review this program before adoption. Questions: "
"compliance@performancewest.com.")
# ── Optional state DFWP addendum ───────────────────────────────────────
if state_dfwp:
b.page_break()
b.h1(f"Addendum — {state_dfwp} Drug-Free Workplace Program")
b.body(
f"In addition to your federal DOT program, {company} maintains a "
f"Drug-Free Workplace Program consistent with {state_dfwp} law. This "
"program runs alongside (and does not replace) the DOT testing "
"program in this binder.")
b.bullets([
"The Company prohibits the unlawful manufacture, distribution, "
"possession, or use of controlled substances in the workplace.",
"Employees must notify the Company of any criminal drug-statute "
"conviction for a violation occurring in the workplace, as required "
"by state law.",
"The Company makes a good-faith effort to maintain a drug-free "
"workplace through this policy, the awareness materials in Section "
"7, and available counseling and treatment resources.",
f"State-specific notice, testing, and appeal rights under "
f"{state_dfwp} law apply where they exceed federal requirements; DOT "
"rules always govern DOT-required tests.",
])
b.small(
f"Confirm your {state_dfwp} program registration, premium-discount, "
"and notice requirements with the state agency or your insurer, and "
"have counsel review. We can help — compliance@performancewest.com.")
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
doc.save(str(out))
LOG.info("Generated D&A binder DOCX (%s mode) -> %s", mode, out)
return str(out)
# ── Header / footer ─────────────────────────────────────────────────────────
def _add_header_footer(doc, meta, carrier_name):
section = doc.sections[0]
# Header
hp = section.header.paragraphs[0]
hp.text = ""
r = hp.add_run("DOT Drug & Alcohol Compliance Program")
r.bold = True
r.font.size = Pt(8)
r.font.color.rgb = NAVY
if carrier_name:
r2 = hp.add_run(" \u2022 " + carrier_name[:48])
r2.font.size = Pt(8)
r2.font.color.rgb = SLATE
# Footer with page number field
fp = section.footer.paragraphs[0]
fp.text = ""
r = fp.add_run(f"Performance West Inc. \u2022 {meta['part']} Page ")
r.font.size = Pt(7.5)
r.font.color.rgb = SLATE
_add_page_field(fp)
def _add_page_field(paragraph):
run = paragraph.add_run()
fldChar1 = OxmlElement("w:fldChar")
fldChar1.set(qn("w:fldCharType"), "begin")
instrText = OxmlElement("w:instrText")
instrText.set(qn("xml:space"), "preserve")
instrText.text = "PAGE"
fldChar2 = OxmlElement("w:fldChar")
fldChar2.set(qn("w:fldCharType"), "end")
run._r.append(fldChar1)
run._r.append(instrText)
run._r.append(fldChar2)
run.font.size = Pt(7.5)
run.font.color.rgb = SLATE
# ── Forms (each starts a fresh page, fills a page) ──────────────────────────
def _form_header(b, code, title):
b.page_break()
b.h2(f"Form {code}{title}")
def _form_a(b, carrier_name, meta):
_form_header(b, "A", "Employee Policy Receipt & Acknowledgment")
b.body(
f"I acknowledge that I have received, read, and understand the "
f"{carrier_name or 'Company'} Drug & Alcohol Testing Policy adopted "
f"under {meta['part']}, together with the educational materials on the "
"effects and signs of alcohol and controlled-substance use. I "
"understand that I am subject to pre-employment, random, reasonable-"
"suspicion, post-accident, return-to-duty, and follow-up testing, and "
"that a verified positive test, an alcohol concentration of 0.04 or "
"greater, or a refusal will remove me from safety-sensitive duty and "
"require completion of the DOT return-to-duty process before I may "
"return.")
b.body(
"I understand who the Designated Employer Representative (DER) is and "
"how to contact the DER with questions, and where to find treatment and "
"Employee Assistance resources.")
b.spacer(14)
for label in [
"Employee name (print):",
"Employee signature:",
"Date: Position:",
"DER / witness (print):",
"DER / witness signature:",
]:
b.fill_line(label + " " + "_" * max(6, 70 - len(label)), gap=18)
b.small(
"Keep the signed original in the employee's file for the duration of "
"employment plus one year.")
def _form_b(b, carrier_name, meta):
_form_header(b, "B", "Pre-Employment Consent & Prior-Employer Inquiry")
b.body(
f"Complete before a new covered employee performs safety-sensitive "
f"functions for {carrier_name or 'the Company'}. The applicant consents "
"to a DOT pre-employment drug test and to the Company's inquiry to "
"prior DOT employers about the applicant's DOT testing history.")
b.h3("Applicant consent")
b.body(
"I consent to a DOT pre-employment controlled-substances test and "
"authorise the Company to obtain my DOT drug and alcohol testing "
"history (including positives, refusals, and completed return-to-duty "
"follow-up) from my DOT-regulated employers for the past three years. "
"For CDL positions, I consent to the FMCSA Clearinghouse pre-employment "
"full query.")
b.spacer(10)
for label in [
"Applicant name (print):",
"Signature: Date:",
"Position applied for:",
"Prior DOT employer(s) contacted:",
]:
b.fill_line(label + " " + "_" * max(6, 66 - len(label)), gap=16)
b.h3("Company use — prior-employer / query results")
for label in [
"Pre-employment drug test result: [ ] Negative [ ] Positive "
"[ ] Refusal",
"Clearinghouse pre-employment full query: [ ] No prohibited status "
"[ ] Prohibited",
"Prior-employer information received: [ ] Yes [ ] No [ ] No prior "
"DOT employer",
"Cleared to perform safety-sensitive functions: [ ] Yes [ ] No",
"DER (print): Signature / date:",
]:
b.fill_line(label, gap=14)
b.small("Retain for the duration of employment plus the required period.")
def _form_c(b, carrier_name):
_form_header(b, "C", "Test Notification / Authorization to Test")
b.body(
"Use to notify an employee that they have been selected or directed for "
"a DOT test and to document the chain of timing. Give one copy to the "
"employee and keep one for the file.")
b.spacer(8)
for label in [
"Employee name (print):",
"USDOT # / Company:",
"Reason for test: [ ] Random [ ] Reasonable suspicion "
"[ ] Post-accident [ ] Return-to-duty [ ] Follow-up "
"[ ] Pre-employment",
"Type of test: [ ] Drug [ ] Alcohol [ ] Both",
"Date/time employee notified:",
"Collection site name / address:",
"Date/time employee directed to report:",
"Date/time employee arrived at collection site:",
"Notes / delays (a delay or failure to proceed may be a refusal):",
]:
b.fill_line(label + " " + "_" * max(4, 64 - len(label)), gap=14)
b.blank_lines(2)
for label in [
"Employee signature: Date:",
"DER / supervisor (print): Signature:",
]:
b.fill_line(label + " " + "_" * max(4, 60 - len(label)), gap=16)
b.small("Retain per the recordkeeping schedule in Section 8.")
def _form_d(b, carrier_name):
_form_header(b, "D", "Reasonable-Suspicion Observation Record")
b.body(
"Complete immediately when directing an employee to a reasonable-"
"suspicion test. Must be made by a supervisor trained per Section 5 and "
"signed and dated within 24 hours of the observations.")
b.spacer(8)
for label in [
"Employee observed (print):",
"Date / time of observation:",
"Location:",
]:
b.fill_line(label + " " + "_" * max(4, 60 - len(label)), gap=14)
b.body(
"Specific observations (appearance, behavior, speech, odor, "
"coordination, performance) — be factual and contemporaneous:")
b.blank_lines(5)
for label in [
"Test directed: [ ] Drug [ ] Alcohol [ ] Both",
"Employee removed from safety-sensitive duty: [ ] Yes [ ] No",
"Trained supervisor (print):",
"Supervisor signature: Date:",
]:
b.fill_line(label + (" " + "_" * max(4, 56 - len(label))
if ":" in label and "[ ]" not in label else ""),
gap=14)
b.small(
"Retain for 5 years. The supervisor must have completed the required "
"120 minutes of reasonable-suspicion training (see Form F).")
def _form_e(b, carrier_name):
_form_header(b, "E", "Post-Accident Testing Decision Worksheet")
b.body(
"Use immediately after any accident to decide whether DOT post-accident "
"testing is required. **Test if ANY box below is checked.**")
b.spacer(6)
for label in [
"[ ] The accident involved a **fatality**.",
"[ ] The driver received a **citation** AND a person was **injured and "
"required medical treatment away from the scene**.",
"[ ] The driver received a **citation** AND a **vehicle was towed** "
"from the scene due to disabling damage.",
]:
b.fill_line(label, gap=8)
b.spacer(6)
b.body(
"If testing is required: conduct the **alcohol test within 8 hours** "
"(as soon as possible) and the **drug test within 32 hours**. Do not "
"let the driver consume alcohol before the alcohol test. Document any "
"reason a required test could not be completed.")
b.spacer(10)
for label in [
"Driver (print):",
"Date / time of accident:",
"Citation issued to driver: [ ] Yes [ ] No",
"Decision: [ ] Test required [ ] Not required",
"Alcohol test completed (date/time):",
"Drug test completed (date/time):",
"DER (print): Signature / date:",
]:
b.fill_line(label + (" " + "_" * max(4, 56 - len(label))
if "[ ]" not in label else ""), gap=14)
b.small("Retain for 5 years, including any decision NOT to test.")
def _form_f(b, carrier_name):
_form_header(b, "F", "Supervisor Training Completion Record")
b.body(
f"Record each supervisor who has completed the {('')} required "
"reasonable-suspicion training: at least 60 minutes on alcohol misuse "
"and at least 60 minutes on controlled-substance use (120 minutes "
"total). Keep this record on file and produce it on audit.")
b.spacer(6)
b.table(
["Supervisor name", "Alcohol (min)", "Drugs (min)", "Date", "Trainer / source"],
[["", "", "", "", ""] for _ in range(8)],
[2.2, 0.9, 0.9, 0.9, 1.6],
alt=False,
)
b.spacer(10)
for label in [
"DER (print): Signature / date:",
]:
b.fill_line(label + " " + "_" * 20, gap=14)
b.small(
"A supervisor must complete this training before making any "
"reasonable-suspicion testing decision.")
# ── Misc helpers ────────────────────────────────────────────────────────────
def _covered_count(cdl_drivers, owner_operators) -> str:
try:
n = int(str(cdl_drivers).strip() or 0)
except (TypeError, ValueError):
n = 0
try:
oo = int(str(owner_operators).strip() or 0)
except (TypeError, ValueError):
oo = 0
total = n + oo
if total <= 0:
return ""
extra = f" ({oo} owner-operator)" if oo else ""
return f"{total} covered position(s){extra}"