""" 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-G), each on its own page 10. The regulations (citations + how to read the actual rule text) 11. Practical guidance for the administrator (owner-operators, audits/ penalties, problem results, marijuana/CBD, refusals, costs, do's & don'ts) (+ 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 section_rule(self, space_before=14, space_after=2): """A light divider between sections that share a page (no page break).""" p = self.doc.add_paragraph() p.paragraph_format.space_before = Pt(space_before) p.paragraph_format.space_after = Pt(space_after) 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"), "4") bottom.set(qn("w:space"), "1") bottom.set(qn("w:color"), "DBE2EA") pbdr.append(bottom) pPr.append(pbdr) return p def _panel_into_cell(self, cell, title, lead, items): """Render a titled resource panel inside a table cell.""" cell.text = "" tp = cell.paragraphs[0] tp.paragraph_format.space_after = Pt(2) tr = tp.add_run(title) tr.bold = True tr.font.size = Pt(11) tr.font.color.rgb = NAVY if lead: lp = cell.add_paragraph() lp.paragraph_format.space_after = Pt(3) lr = lp.add_run(lead) lr.italic = True lr.font.size = Pt(8.5) lr.font.color.rgb = SLATE for it in items: ip = cell.add_paragraph() ip.paragraph_format.space_after = Pt(2) ip.paragraph_format.left_indent = Inches(0.13) ip.paragraph_format.first_line_indent = Inches(-0.13) bullet = ip.add_run("\u2022 ") bullet.font.size = Pt(9) bullet.font.color.rgb = BLUE _add_runs(ip, it) for r in ip.runs[1:]: r.font.size = Pt(9) r.font.color.rgb = INK def two_col_panels(self, panels): """Lay out (title, lead, [items]) panels in two columns, borderless.""" rows = (len(panels) + 1) // 2 t = self.doc.add_table(rows=rows, cols=2) t.alignment = WD_TABLE_ALIGNMENT.CENTER t.autofit = False for col in t.columns: for cell in col.cells: cell.width = Inches(3.35) for i, panel in enumerate(panels): r, c = divmod(i, 2) self._panel_into_cell(t.rows[r].cells[c], *panel) tblPr = t._tbl.tblPr borders = OxmlElement("w:tblBorders") for edge in ("top", "left", "bottom", "right", "insideH", "insideV"): el = OxmlElement(f"w:{edge}") el.set(qn("w:val"), "none") el.set(qn("w:sz"), "0") el.set(qn("w:space"), "0") borders.append(el) tblPr.append(borders) return t 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 checkbox(self, text, *, size=10.5, gap=5, indent=0.3): """A checklist line beginning with an open box glyph.""" p = self.doc.add_paragraph() p.paragraph_format.space_after = Pt(gap) p.paragraph_format.left_indent = Inches(indent) p.paragraph_format.first_line_indent = Inches(-0.22) box = p.add_run("\u2750 ") # open ballot box box.font.size = Pt(size + 1) box.font.color.rgb = NAVY _add_runs(p, text) for r in p.runs[1:]: r.font.size = Pt(size) r.font.color.rgb = INK return p 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() # ── DER Quick-Start Checklist (tear-off first page) ───────────────────── _der_quickstart(b, meta, der_name, der_title, provider_name, random_rate) # ── Table of contents ─────────────────────────────────────────────────── b.h1("What's Inside This Binder") b.body( "Start with the **DER Quick-Start Checklist** on the previous page, " "then use the sections below for the detail.") 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-G).** 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.", "**Section 11 — Practical Guidance for the Administrator.** Real-world " "answers: owner-operators, audits and penalties, problem test results, " "prescriptions/marijuana/CBD, what counts as a refusal, costs, and the " "DER's do's and don'ts.", "**Suggested Vendors & Resources.** A two-column directory of the " "consortiums, labs, MRO/SAP, and training providers you'll need.", ]) 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.h3("Enrolling a driver (new-hire onboarding)") b.body( "Every covered employee must be enrolled in your testing program and " "random pool, and must pass a pre-employment drug test, **before** they " "first perform safety-sensitive functions. Use Form G to capture each " "driver's information and add them to your roster. Follow this sequence " "for every new hire:") enroll = [ "**Collect the driver's information** (Form G): full legal name, date " "of birth, the last four digits of the SSN (or the full SSN if your " "C-TPA requires it for lab matching), CDL number and state, address, " "phone, email, hire date, and position.", "**Have the driver sign Form A** (policy acknowledgment) and **Form B** " "(pre-employment consent and prior-employer release).", ] if meta.get("clearinghouse"): enroll.append( "**Run the FMCSA Clearinghouse pre-employment full query** (with " "the driver's electronic consent in the Clearinghouse) and confirm " "the driver is **not prohibited**.") enroll.append( "**Request the prior-employer DOT testing history** for the past " "three years (Form B); for CDL drivers the Clearinghouse covers " "violations on/after 1/6/2020 — still request manual records for " "the period before that.") else: enroll.append( "**Request the prior-employer DOT testing history** for the past " "two years (Form B) and document the inquiry.") enroll += [ "**Add the driver to your C-TPA roster / random pool.** Send Form G to " f"{provider_name} (or enter it in their portal) so the driver is in the " "next random selection. Do this on or before the hire date.", "**Send the driver for the pre-employment drug test** at an approved " "collection site. The site uses the federal chain-of-custody form " "(CCF) — you do not supply it. Give the driver the collection site " "name, address, hours, and any donor pass/authorization your C-TPA " "issues.", "**Wait for the MRO-verified negative result** before letting the " "driver perform any safety-sensitive function. Keep the negative " "result and all enrollment records in the driver's confidential file.", ] b.numbered(enroll) b.body( "**Removing a driver:** when a covered employee leaves or stops " "performing safety-sensitive functions, notify your C-TPA to remove " "them from the random pool and note the departure on your roster " "(Form G). Keep their records for the required retention period " "(Section 8).") b.section_rule() # ── 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.section_rule() # ── 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.section_rule() # ── 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.section_rule() # ── 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.section_rule() # ── 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.section_rule() # ── 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.section_rule() # ── 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.section_rule() # ── 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 G** — Driver Enrollment & Covered-Employee Roster.", ]) _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) _form_g(b, carrier_name, meta, provider_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.") # ── Section 11 — Practical guidance for the administrator ─────────────── _section_practical_guidance(b, meta, company, random_rate) # ── Suggested vendors & resources (two-column) ────────────────────────── _vendor_directory(b, meta) # ── 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) # ── DER Quick-Start Checklist (one-page tear-off) ─────────────────────────── def _der_quickstart(b, meta, der_name, der_title, provider_name, random_rate): b.h1("DER Quick-Start Checklist") b.body( "A one-page summary for the Designated Employer Representative (DER). " "Work top to bottom: do the SET-UP items once, then run the EVERY-HIRE " "and ONGOING items continuously. Each item points to the section or " "form with the detail. Tear this page out and keep it handy.", italic=True) b.h3("Set up once") setup = [ "**Name the DER and a backup** (cover page). DER: " f"{der_name or '____________________'}.", "**Adopt & sign the written policy** (Section 2).", f"**Join / confirm your consortium (C-TPA):** {provider_name} " "(Sections 1 & 4).", "**Train every supervisor** 120 minutes before any reasonable-suspicion " "decision (Section 5; Form F).", ] if meta.get("clearinghouse"): setup.append( "**Register with the FMCSA Clearinghouse** and designate your " "C-TPA (Section 1).") for item in setup: b.checkbox(item) b.h3("Every new hire (before they drive)") hire = [ "**Collect driver info & add to the random pool** (Form G).", "**Get signed Form A** (policy ack.) **and Form B** (consent / prior-" "employer inquiry).", ] if meta.get("clearinghouse"): hire.append( "**Run the Clearinghouse pre-employment full query** — confirm " "**not prohibited**.") hire += [ "**Send for the pre-employment drug test;** wait for the MRO **verified " "negative** before any safety-sensitive work (Section 3).", ] for item in hire: b.checkbox(item) b.h3("Ongoing") ongoing = [ f"**Random testing** all year at {random_rate}; send selected drivers " "**immediately**, no warning (Section 4).", "**Reasonable suspicion** — trained supervisor documents it (Form D).", "**Post-accident** — use the decision worksheet at the scene (Form E).", "**Keep the roster current** (add hires, remove departures) (Form G).", "**Act on any positive / 0.04+ / refusal the SAME day** — remove from " "duty, start the SAP / return-to-duty process (Section 6).", "**Keep records** confidential and for the required period (Section 8).", ] if meta.get("clearinghouse"): ongoing.append( "**Annual Clearinghouse limited query** on every CDL driver; " "**report** violations within the required timeframes (Section 1).") for item in ongoing: b.checkbox(item) b.body( "**Stuck or unsure?** See Section 11 (owner-operators, audits, problem " "results, marijuana/CBD, refusals) or call your C-TPA/MRO. Questions: " "compliance@performancewest.com.") b.page_break() # ── Section 11 — Practical guidance ───────────────────────────────────────── def _section_practical_guidance(b, meta, company, random_rate): b.section_rule() b.h1("Section 11 — Practical Guidance for the Administrator") b.body( "The regulations tell you what to do; this section covers the real-" "world questions a program administrator runs into. It is practical " "guidance, not legal advice — when a situation is serious or unclear, " "call your C-TPA/MRO or counsel.") b.h2("Owner-operators and one-driver companies") b.body( "This is the most misunderstood situation. If you are an owner-operator " "or a one-driver carrier, you are **both the employer and the covered " "employee** — and you may **not** test yourself or run your own random " "selection.") b.bullets([ "You **must** join a consortium (C-TPA). The consortium puts you in a " "pool with other drivers and does the random selection for you, so the " "selection is genuinely random and out of your hands.", "You cannot be your own DER for results handling in a way that defeats " "the rule; the C-TPA/MRO handles results and notifies you.", "You still need a pre-employment negative, you are still subject to " "random/post-accident/reasonable-suspicion (someone else must observe " "for reasonable suspicion), and you still keep all records.", "When you add a driver, you become the employer for that driver and " "take on full DER duties for them.", ]) b.h2("Audits, penalties, and the new-entrant safety audit") b.body( "A new motor carrier typically gets a **new-entrant safety audit** in " "its first 12 months, and any carrier can be audited later. The " "auditor will ask to see your testing program. Have these ready:") b.bullets([ "Your written policy and signed employee acknowledgments (Form A).", "Proof of consortium/C-TPA enrollment and your random-selection records " "and annual rate calculation.", "Pre-employment negative results for every driver before they drove.", "Supervisor training certificates (Form F).", "Any post-accident, reasonable-suspicion, return-to-duty, and follow-up " "records.", ]) if meta.get("clearinghouse"): b.bullets([ "FMCSA Clearinghouse: proof of pre-employment full queries and " "annual limited queries on every CDL driver, and that you reported " "any violations.", ]) b.body( "**Why this matters:** missing or no testing program is one of the most " "common automatic safety-audit failures. It can lead to civil " "penalties, a failed new-entrant audit (revoked operating authority), " "and drivers placed **out of service**. A driver who tests positive, " "refuses, or is 'prohibited' may not operate a CMV.") b.h2("Problem test results — what to do") b.body("Not every test comes back a clean negative. Know these:") b.bullets([ "**Dilute (negative-dilute):** usually you may (and sometimes must) " "direct an immediate recollection under your policy — follow the MRO's " "instruction. A positive-dilute is treated as a positive.", "**Shy bladder / insufficient specimen:** the collector follows a set " "procedure (water, up to three hours). If the employee still cannot " "provide enough, the MRO refers them for a medical evaluation; an " "unexplained failure is a **refusal**.", "**Cancelled test:** a test cancelled for a fatal/correctable flaw is " "neither positive nor negative; the MRO/C-TPA will tell you whether a " "recollection is required (for pre-employment, return-to-duty, and " "follow-up tests, a recollection is required).", "**Split-specimen request:** an employee may, within 72 hours of being " "told of a verified positive/adulterated/substituted result, request " "that the split (Bottle B) be tested at a second lab — at their cost. " "Do not remove this right; the MRO handles it.", ]) b.h2("Prescriptions, marijuana, and CBD") b.bullets([ "**Marijuana is prohibited** for safety-sensitive employees under " "federal law **regardless of state legalization** or a state medical-" "marijuana card. A marijuana positive is a violation.", "**CBD is a trap.** CBD products are unregulated and may contain enough " "THC to cause a positive. Using CBD is **not** a valid medical " "explanation to the MRO. Warn your drivers in writing.", "**Legitimate prescriptions:** the MRO — not you — evaluates whether a " "prescription explains a positive. Drivers should keep prescriptions " "current and tell the MRO (not the employer) if contacted. A driver " "must not perform safety-sensitive duty on any medication a prescriber " "has warned against.", "Do not ask drivers to disclose their medications to you; that can " "create ADA/privacy problems. Route medical questions to the MRO.", ]) b.h2("What counts as a refusal") b.body( "A refusal is treated exactly like a verified positive and triggers the " "full return-to-duty process. Refusals include:") b.bullets([ "Failing to appear for a test within a reasonable time, or leaving the " "collection site before the process is complete.", "Failing to provide a specimen (without a valid medical reason), or " "failing the shy-bladder/insufficient-specimen evaluation.", "Refusing to be observed for a directly observed (return-to-duty or " "follow-up) collection.", "Adulterating, substituting, or tampering with a specimen, or admitting " "the specimen was altered.", "Failing or declining to take a second test the employer or collector " "directs.", ]) b.body( "Document the time and circumstances (Form C is useful here) and treat " "it as a violation — do not let the employee continue safety-sensitive " "work.") b.h2("Costs and timeline — set expectations") b.bullets([ "Typical out-of-pocket costs: consortium/C-TPA enrollment and per-" "driver annual fees, the per-test collection/lab/MRO fee, and " "supervisor training. Your provider can give you current pricing.", "A pre-employment result is usually back within a couple of business " "days (longer if the MRO must investigate a non-negative).", "After a violation, the SAP and return-to-duty process is typically " "weeks to months and is generally at the employee's expense; you are " "not required to return anyone to duty.", ]) b.h2("DER do's and don'ts") b.bullets([ "**Do** act on a positive/refusal the **same day** — remove the " "employee from safety-sensitive duty immediately.", "**Do** keep D&A records **separate and confidential** — not in the " "general personnel file, and not shared with people who don't need to " "know.", "**Do** keep your consortium roster current; an out-of-date roster " "skews your random rate and fails audits.", "**Don't** warn or 'tip off' a randomly selected employee, delay their " "collection, or let them go home first.", "**Don't** accept a home/instant test or a non-DOT test in place of a " "DOT-required test.", "**Don't** try to interpret results yourself — the MRO verifies; you " "act on what the MRO/C-TPA reports.", "**When in doubt, call** your C-TPA, MRO, or counsel before acting. " "Questions: compliance@performancewest.com.", ]) # ── Suggested vendors & resources (two-column directory) ──────────────────── def _vendor_directory(b, meta): b.page_break() b.h1("Suggested Vendors & Resources") b.body( "Setting up your program means lining up a few service providers. The " "panels below group the vendors a carrier typically needs, with " "well-known national options as a starting point. These are examples " "to help you shop, **not endorsements** — compare service, coverage, " "and price, and confirm each provider meets DOT requirements. The " "simplest path for most small carriers is a single Consortium/Third-" "Party Administrator (C-TPA) that bundles the pool, scheduling, " "collection network, lab, and MRO.", italic=True) panels = [ ( "Consortium / C-TPA (bundles everything)", "Manages your random pool, scheduling, collection, lab & MRO.", [ "**US Drug Test Centers** — usdrugtestcenters.com", "**Foundation / DISA Global Solutions** — disa.com", "**National Compliance Management Service (NCMS)** — " "ncmsmro.com", ], ), ( "Collection sites & SAMHSA-certified labs", "Where the specimen is collected and analyzed (DOT 5-panel).", [ "**Quest Diagnostics** — questdiagnostics.com (nationwide " "Patient Service Centers)", "**Labcorp** — labcorp.com / labcorpdrugtesting.com", "**Any Lab Test Now** — anylabtestnow.com", "Your C-TPA assigns the nearest approved collection site.", ], ), ( "Medical Review Officer (MRO)", "Licensed physician who verifies non-negative results.", [ "Usually **included with your C-TPA** — confirm before signing.", "**American Association of MROs (AAMRO)** — aamro.com " "(verify/locate an MRO)", "**NCMS** MRO services (see C-TPA panel).", ], ), ( "Substance Abuse Professional (SAP)", "Required after a violation, for return-to-duty.", [ "**DOT SAP locator & guidance** — transportation.gov/odapc", "**SAPlist.com** — directory of qualified SAPs", "Ask your C-TPA for SAP referrals in the driver's area.", ], ), ( "Supervisor reasonable-suspicion training", "120 minutes (60 alcohol + 60 drugs) before any decision.", [ "**J. J. Keller** — jjkeller.com", "**US Drug Test Centers** online courses (see C-TPA panel).", "Many C-TPAs include a DOT-compliant supervisor course.", ], ), ] if meta.get("clearinghouse"): panels.append(( "FMCSA Clearinghouse (CDL drivers)", "Register, designate your C-TPA, run queries, report violations.", [ "**Official site** — clearinghouse.fmcsa.dot.gov", "Your C-TPA can run queries and reporting on your behalf once " "you designate them.", "**FMCSA help** — 844-955-0207", ], )) else: panels.append(( "Official DOT / agency resources", "Free, authoritative guidance and forms.", [ f"**{meta['agency']}** rule: ecfr.gov (search the part number)", "**DOT ODAPC** — transportation.gov/odapc", ], )) panels.append(( "Help & treatment (for employees)", "Give these to employees with the policy (Section 7).", [ "**SAMHSA Helpline** — 1-800-662-HELP (4357), 24/7", "**findtreatment.gov** — treatment locator", "**988** Suicide & Crisis Lifeline (call/text)", ], )) b.two_col_panels(panels) b.small( "Listing a provider here is not an endorsement and Performance West " "receives no fee for these listings unless noted. Verify current " "pricing, coverage, and DOT compliance directly with each vendor. " "Need help choosing? Email compliance@performancewest.com.") # ── 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.") def _form_g(b, carrier_name, meta, provider_name): _form_header(b, "G", "Driver Enrollment & Covered-Employee Roster") b.body( f"Complete one enrollment block for each covered employee of " f"{carrier_name or 'the Company'} and add them to the roster below. " f"Send the information to {provider_name} so the employee is placed in " "the random pool, and keep this form in your records. Enroll a driver " "**before** they perform any safety-sensitive function.") b.h3("New-driver enrollment") for label in [ "Full legal name:", "Date of birth: SSN (last 4): ____ ____", "CDL number: CDL state:", "Address:", "Phone: Email:", "Position / job title:", "Hire date: Date added to random pool:", ]: b.fill_line(label + " " + "_" * max(4, 58 - len(label)), gap=15) b.spacer(4) for label in [ "Pre-employment drug test result: [ ] Negative [ ] Pending " "[ ] Positive/Refusal (do NOT place on duty)", ]: b.fill_line(label, gap=8) if meta.get("clearinghouse"): b.fill_line( "Clearinghouse pre-employment full query: [ ] Not prohibited " "[ ] Prohibited Date run: ____________", gap=8) b.fill_line( "Prior-employer DOT testing history requested: [ ] Yes [ ] No " "[ ] No prior DOT employer", gap=8) b.fill_line( "Forms collected: [ ] Form A (policy ack.) [ ] Form B " "(consent/inquiry)", gap=12) b.h3("Covered-employee roster") b.body( "Keep this roster current. Add each new hire and mark the date a " "departing employee was removed from the random pool.", italic=True) b.table( ["Employee name", "CDL # / state", "Position", "Added to pool", "Removed (date)"], [["", "", "", "", ""] for _ in range(9)], [2.0, 1.4, 1.1, 1.0, 1.1], alt=False, ) b.small( "Retain enrollment records and the negative pre-employment result in " "each driver's confidential file. Notify your C-TPA promptly of every " "addition and removal so your random rate stays accurate.") # ── 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}"