Prescription audit checklist pdf
prescription audit checklist pharmacy hospital components
mkdir -p /tmp/workspace/prescription-audit && ls /tmp/workspace/prescription-audit/
~/prescription-audit/generate_checklist.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import (
SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,
HRFlowable, KeepTogether
)
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.graphics.shapes import Drawing, Rect
from reportlab.pdfgen import canvas
import os
OUTPUT_PATH = "/tmp/workspace/prescription-audit/Prescription_Audit_Checklist.pdf"
# ── Colour palette ──────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1B3A6B")
TEAL = colors.HexColor("#1A7F8E")
LIGHT_BG = colors.HexColor("#EAF4F6")
MED_GRAY = colors.HexColor("#5A5A5A")
LIGHT_ROW = colors.HexColor("#F5FAFC")
ALT_ROW = colors.HexColor("#DDEEF2")
WHITE = colors.white
RED_WARN = colors.HexColor("#C0392B")
GREEN_OK = colors.HexColor("#1E8449")
ORANGE = colors.HexColor("#D35400")
PAGE_W, PAGE_H = A4
MARGIN = 18 * mm
# ── Helper: checkbox cell ────────────────────────────────────────────────────
CHECKBOX = u"\u2610" # ☐
CHECKED = u"\u2611" # ☑ (unused but handy)
# ── Canvas callback for header/footer ───────────────────────────────────────
def header_footer(canvas_obj, doc):
canvas_obj.saveState()
w, h = A4
# Top bar
canvas_obj.setFillColor(NAVY)
canvas_obj.rect(0, h - 20*mm, w, 20*mm, fill=1, stroke=0)
canvas_obj.setFont("Helvetica-Bold", 13)
canvas_obj.setFillColor(WHITE)
canvas_obj.drawCentredString(w / 2, h - 12*mm, "PRESCRIPTION AUDIT CHECKLIST")
canvas_obj.setFont("Helvetica", 8)
canvas_obj.drawString(MARGIN, h - 17*mm, "Hospital / Clinical Pharmacy Use")
canvas_obj.drawRightString(w - MARGIN, h - 17*mm, f"Page {doc.page}")
# Bottom bar
canvas_obj.setFillColor(TEAL)
canvas_obj.rect(0, 0, w, 8*mm, fill=1, stroke=0)
canvas_obj.setFillColor(WHITE)
canvas_obj.setFont("Helvetica", 7)
canvas_obj.drawCentredString(
w / 2, 2.5*mm,
"Confidential | For Internal Audit Use Only | Retain as per institutional policy"
)
canvas_obj.restoreState()
# ── Build document ───────────────────────────────────────────────────────────
doc = SimpleDocTemplate(
OUTPUT_PATH,
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=26*mm, bottomMargin=14*mm,
title="Prescription Audit Checklist",
author="Clinical Pharmacy / Quality Assurance",
)
styles = getSampleStyleSheet()
# Custom styles
def S(name, **kw):
return ParagraphStyle(name, **kw)
sTitle = S("sTitle", fontName="Helvetica-Bold", fontSize=14,
textColor=NAVY, spaceAfter=2, alignment=TA_CENTER)
sSection = S("sSection", fontName="Helvetica-Bold", fontSize=9,
textColor=WHITE, spaceAfter=0, spaceBefore=0, alignment=TA_LEFT)
sBody = S("sBody", fontName="Helvetica", fontSize=8,
textColor=MED_GRAY, leading=11, spaceAfter=1)
sBold = S("sBold", fontName="Helvetica-Bold", fontSize=8,
textColor=colors.black, leading=11)
sSmall = S("sSmall", fontName="Helvetica", fontSize=7,
textColor=MED_GRAY, leading=9)
sNote = S("sNote", fontName="Helvetica-Oblique", fontSize=7.5,
textColor=ORANGE, leading=10, spaceAfter=2)
sField = S("sField", fontName="Helvetica", fontSize=8,
textColor=colors.black, leading=11)
story = []
# ── SECTION HEADER helper ────────────────────────────────────────────────────
def section_header(number, title, subtitle=""):
label = f" {number}. {title}"
if subtitle:
label += f" — {subtitle}"
t = Table([[Paragraph(label, sSection)]], colWidths=[PAGE_W - 2*MARGIN])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), TEAL),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 6),
("BOX", (0,0), (-1,-1), 0.5, NAVY),
]))
return t
# ── CHECKLIST TABLE helper ───────────────────────────────────────────────────
def checklist_table(rows, col_widths=None):
"""
rows: list of (item_text, yes/no/na columns, remarks)
Each data row: [checkbox+text, Y, N, NA, Remarks_________]
"""
header = [
Paragraph("<b>#</b>", sBold),
Paragraph("<b>Audit Parameter</b>", sBold),
Paragraph("<b>Yes</b>", sBold),
Paragraph("<b>No</b>", sBold),
Paragraph("<b>N/A</b>", sBold),
Paragraph("<b>Remarks</b>", sBold),
]
data = [header]
for i, (text, remark) in enumerate(rows, 1):
data.append([
Paragraph(f"<b>{i}</b>", sSmall),
Paragraph(text, sBody),
CHECKBOX, CHECKBOX, CHECKBOX,
Paragraph(remark, sSmall),
])
cw = col_widths or [8*mm, 92*mm, 10*mm, 10*mm, 10*mm, 40*mm]
t = Table(data, colWidths=cw, repeatRows=1)
style = [
# Header
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,0), 8),
("ALIGN", (0,0), (-1,0), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 4),
# Alternating rows
("BOX", (0,0), (-1,-1), 0.5, NAVY),
("INNERGRID", (0,0), (-1,-1), 0.3, colors.HexColor("#B0C8D0")),
# Checkbox columns centred
("ALIGN", (2,1), (4,-1), "CENTER"),
("FONTSIZE", (2,1), (4,-1), 11),
]
for r in range(1, len(data)):
bg = LIGHT_ROW if r % 2 == 1 else ALT_ROW
style.append(("BACKGROUND", (0,r), (-1,r), bg))
t.setStyle(TableStyle(style))
return t
# ── INFO GRID helper (label: _____ pairs) ────────────────────────────────────
def info_grid(fields, cols=2):
"""fields: list of label strings; rendered as label + underline pairs."""
rows = []
row = []
for i, f in enumerate(fields):
cell = Table(
[[Paragraph(f"<b>{f}:</b>", sBold)],
[HRFlowable(width="100%", thickness=0.5, color=TEAL)]],
colWidths=[(PAGE_W - 2*MARGIN) / cols - 4*mm]
)
row.append(cell)
if len(row) == cols:
rows.append(row)
row = []
if row:
while len(row) < cols:
row.append("")
rows.append(row)
cw = [(PAGE_W - 2*MARGIN) / cols] * cols
t = Table(rows, colWidths=cw, hAlign="LEFT")
t.setStyle(TableStyle([
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 6),
("LEFTPADDING", (0,0), (-1,-1), 4),
("VALIGN", (0,0), (-1,-1), "BOTTOM"),
]))
return t
# ────────────────────────────────────────────────────────────────────────────
# DOCUMENT CONTENT
# ────────────────────────────────────────────────────────────────────────────
# ── Cover meta block ─────────────────────────────────────────────────────────
meta_data = [
[Paragraph("<b>Institution / Hospital Name:</b>", sBold), "",
Paragraph("<b>Department / Ward:</b>", sBold), ""],
[HRFlowable(width="100%", thickness=0.5, color=TEAL), "",
HRFlowable(width="100%", thickness=0.5, color=TEAL), ""],
[Paragraph("<b>Auditor Name & Designation:</b>", sBold), "",
Paragraph("<b>Date of Audit:</b>", sBold), ""],
[HRFlowable(width="100%", thickness=0.5, color=TEAL), "",
HRFlowable(width="100%", thickness=0.5, color=TEAL), ""],
[Paragraph("<b>Prescription Ref. No. / Patient ID:</b>", sBold), "",
Paragraph("<b>Audit Period:</b>", sBold), ""],
[HRFlowable(width="100%", thickness=0.5, color=TEAL), "",
HRFlowable(width="100%", thickness=0.5, color=TEAL), ""],
]
cw4 = [55*mm, 35*mm, 45*mm, 35*mm]
meta_tbl = Table(meta_data, colWidths=cw4)
meta_tbl.setStyle(TableStyle([
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 2),
("LEFTPADDING", (0,0), (-1,-1), 2),
("BACKGROUND", (0,0), (-1,-1), LIGHT_BG),
("BOX", (0,0), (-1,-1), 0.8, TEAL),
("SPAN", (1,0), (1,1)),
("SPAN", (3,0), (3,1)),
("SPAN", (1,2), (1,3)),
("SPAN", (3,2), (3,3)),
("SPAN", (1,4), (1,5)),
("SPAN", (3,4), (3,5)),
]))
story.append(Spacer(1, 2*mm))
story.append(Paragraph("Clinical / Hospital Pharmacy | Quality Assurance Division", sBody))
story.append(Spacer(1, 1*mm))
story.append(HRFlowable(width="100%", thickness=1.5, color=TEAL))
story.append(Spacer(1, 2*mm))
story.append(meta_tbl)
story.append(Spacer(1, 4*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 1 — Patient Identification
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("A", "PATIENT IDENTIFICATION"))
story.append(Spacer(1, 1*mm))
story.append(checklist_table([
("Patient name is legibly written on the prescription", ""),
("Patient age / date of birth is recorded", ""),
("Patient gender is documented", ""),
("Patient weight (and height for paediatric/oncology cases) is noted", "Mandatory for dose calculation"),
("Patient unique ID / MRN / IP/OP number is present", ""),
("Ward, bed number, or OPD details are recorded", ""),
("Known allergies (drug / food / contrast) are documented or 'NKDA' stated", "NKDA = No Known Drug Allergy"),
("Diagnosis / indication for prescribed drugs is mentioned", ""),
]))
story.append(Spacer(1, 3*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 2 — Prescriber Information
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("B", "PRESCRIBER INFORMATION"))
story.append(Spacer(1, 1*mm))
story.append(checklist_table([
("Prescriber name is written legibly", ""),
("Prescriber registration number (MCI / State Council) is present", ""),
("Prescriber's designation / specialty is documented", ""),
("Prescriber's contact number / pager is mentioned", ""),
("Date and time of prescription writing are recorded", ""),
("Prescriber's signature is present on each prescription sheet", ""),
("Co-signing / countersigning by consultant (for residents/interns) done where required", "As per institutional policy"),
]))
story.append(Spacer(1, 3*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 3 — Drug Prescribing Standards
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("C", "DRUG PRESCRIBING STANDARDS"))
story.append(Spacer(1, 1*mm))
story.append(checklist_table([
("Drug name written in GENERIC (INN) name, not brand name", "WHO & national policy requirement"),
("Drugs written in CAPITAL LETTERS or legible handwriting / e-prescription", ""),
("Drug formulation / dosage form specified (tablet, syrup, injection, etc.)", ""),
("Dose is clearly mentioned with correct units (mg, mcg, mEq — no ambiguous abbreviations)", "Avoid 'U' for units; write in full"),
("Dose is age / weight / renal / hepatic function appropriate", ""),
("Route of administration is specified (oral, IV, IM, SC, topical, etc.)", ""),
("Frequency / dosing interval is unambiguous (e.g., 'OD', 'BD', 'Q8H' — not 'PRN' without criteria)", ""),
("Duration of therapy is mentioned (days / course length)", ""),
("Total quantity or number of tablets/vials to be dispensed is noted", ""),
("Instructions for administration (with food, dilution, rate of infusion) are provided where relevant", ""),
("Abbreviations used are from the approved / standard list (no dangerous abbreviations)", "E.g., avoid QD, U, IU, trailing zeros"),
("Decimal points used correctly — leading zero present (0.5 mg, not .5 mg)", ""),
("No verbal / telephone orders transcribed without counter-signature within 24 h", ""),
]))
story.append(Spacer(1, 3*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 4 — Rational Drug Use (WHO Core Indicators)
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("D", "RATIONAL DRUG USE (WHO Core Prescribing Indicators)"))
story.append(Spacer(1, 1*mm))
story.append(checklist_table([
("Average number of drugs per encounter is within acceptable range (WHO target: ≤ 2.0)", "Record actual count"),
("Percentage of drugs prescribed by generic name meets institutional target (≥ 80%)", ""),
("Percentage of encounters with an antibiotic meets target (hospital benchmark ≤ 30%)", "Record actual %"),
("Percentage of encounters with an injection meets target", "WHO standard ≤ 17%"),
("Percentage of drugs prescribed from Essential Medicine List (EML) is acceptable (target ≥ 82%)", "National / state EML"),
("Polypharmacy (≥ 5 drugs) — documented clinical justification present if applicable", ""),
("Fixed-Dose Combinations (FDCs) used are approved and clinically justified", ""),
]))
story.append(Spacer(1, 3*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 5 — High-Alert / Controlled Drugs
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("E", "HIGH-ALERT & CONTROLLED DRUGS"))
story.append(Spacer(1, 1*mm))
story.append(checklist_table([
("High-alert drugs (anticoagulants, insulin, concentrated electrolytes, chemotherapy) are flagged / labelled", "Per ISMP / institutional list"),
("Controlled substances (Schedule H1 / narcotics / psychotropics) have appropriate prescription format", "Triplicate / special form as required"),
("Dose of controlled substance written in words as well as figures", ""),
("Quantity of narcotic / Schedule H1 drug is within legally prescribed limit", ""),
("Chemotherapy: protocol name, cycle number, day of cycle, BSA-based dose documented", ""),
("Insulin type, concentration, units, and delivery device specified", ""),
("Anticoagulant — indication, target INR / anti-Xa range, and monitoring plan documented", ""),
]))
story.append(Spacer(1, 3*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 6 — Drug Interaction & Safety Screening
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("F", "DRUG INTERACTION & SAFETY SCREENING"))
story.append(Spacer(1, 1*mm))
story.append(checklist_table([
("Drug-drug interactions (DDIs) checked — major interactions absent or clinically justified", ""),
("Drug-disease contraindications reviewed (e.g., NSAIDs in CKD, beta-blockers in asthma)", ""),
("Drug-allergy cross-check performed against documented allergies", ""),
("Renal dose adjustment applied where creatinine clearance / eGFR indicates", ""),
("Hepatic dose adjustment applied for drugs with significant hepatic metabolism", ""),
("Drug-food interactions counselled / documented (e.g., warfarin-Vitamin K, MAOI-tyramine)", ""),
("Pregnancy / lactation safety category verified where applicable", ""),
("Paediatric dosing verified against standard paediatric formulary", ""),
("Geriatric prescribing — Beers Criteria potentially inappropriate medications reviewed", ""),
]))
story.append(Spacer(1, 3*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 7 — Antimicrobial Stewardship (AMS)
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("G", "ANTIMICROBIAL STEWARDSHIP (AMS)"))
story.append(Spacer(1, 1*mm))
story.append(checklist_table([
("Antibiotic is prescribed with documented indication (prophylaxis / empiric / definitive)", ""),
("Culture and sensitivity (C&S) sample collected before starting antibiotic (if applicable)", ""),
("De-escalation from broad-spectrum to narrow-spectrum antibiotic done on receipt of C&S report", ""),
("Duration of prophylactic antibiotic does not exceed 24 hours (surgical) unless documented exception", ""),
("Restricted / reserve antibiotics prescribed only with AMS / ID team approval", ""),
("IV to oral (IV-to-PO) switch performed when patient clinically stable", ""),
("Antibiotic therapy reviewed at 48–72 hours (antibiotic review sticker / note present)", ""),
("Antifungal / antiviral — appropriate indication and dosing confirmed", ""),
]))
story.append(Spacer(1, 3*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 8 — Dispensing & Transcription Accuracy
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("H", "DISPENSING & TRANSCRIPTION ACCURACY"))
story.append(Spacer(1, 1*mm))
story.append(checklist_table([
("Dispensed drug name matches prescribed drug (no substitution without documented pharmacist/physician approval)", ""),
("Dispensed dose, dosage form, and quantity match prescription", ""),
("Medication Administration Record (MAR) accurately reflects the prescription", ""),
("No transcription errors identified between prescription and MAR", ""),
("Label on dispensed medicine is accurate, legible, and includes all mandatory elements", ""),
("Expiry date of dispensed product checked — not expired", ""),
("Cold-chain / storage requirements met for temperature-sensitive drugs", ""),
("Patient counselling / medication education provided and documented", ""),
]))
story.append(Spacer(1, 3*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 9 — Documentation & Compliance
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("I", "DOCUMENTATION & REGULATORY COMPLIANCE"))
story.append(Spacer(1, 1*mm))
story.append(checklist_table([
("Prescription is on the official institutional prescription pad / e-prescription system", ""),
("Alterations / corrections are countersigned and dated by prescriber (no overwriting/use of correction fluid)", ""),
("Prescription retained / archived as per institutional and legal retention policy", ""),
("Prescription copy available for pharmacist records (where applicable)", ""),
("Adverse Drug Reaction (ADR) reported to pharmacovigilance programme if identified", ""),
("Medication error (near-miss or actual) documented and reported per incident reporting system", ""),
("Informed consent obtained and documented for high-risk / investigational drugs", ""),
]))
story.append(Spacer(1, 4*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION 10 — Summary Score
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("J", "AUDIT SUMMARY & SCORING"))
story.append(Spacer(1, 2*mm))
score_data = [
[Paragraph("<b>Section</b>", sBold),
Paragraph("<b>Total Items</b>", sBold),
Paragraph("<b>Compliant (Yes)</b>", sBold),
Paragraph("<b>Non-Compliant (No)</b>", sBold),
Paragraph("<b>N/A</b>", sBold),
Paragraph("<b>Compliance %</b>", sBold)],
["A Patient Identification", "8", "", "", "", ""],
["B Prescriber Information", "7", "", "", "", ""],
["C Drug Prescribing Standards", "13", "", "", "", ""],
["D Rational Drug Use", "7", "", "", "", ""],
["E High-Alert & Controlled Drugs", "7", "", "", "", ""],
["F Drug Interaction & Safety", "9", "", "", "", ""],
["G Antimicrobial Stewardship", "8", "", "", "", ""],
["H Dispensing & Transcription", "8", "", "", "", ""],
["I Documentation & Compliance", "7", "", "", "", ""],
[Paragraph("<b>TOTAL</b>", sBold),
Paragraph("<b>74</b>", sBold), "", "", "",
Paragraph("<b>______ %</b>", sBold)],
]
scw = [62*mm, 20*mm, 28*mm, 28*mm, 14*mm, 26*mm]
score_tbl = Table(score_data, colWidths=scw, repeatRows=1)
score_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTSIZE", (0,0), (-1,-1), 8),
("ALIGN", (1,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING", (0,0), (-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 5),
("BOX", (0,0), (-1,-1), 0.8, NAVY),
("INNERGRID", (0,0), (-1,-1), 0.3, colors.HexColor("#B0C8D0")),
("BACKGROUND", (0,10), (-1,10), LIGHT_BG),
("FONTNAME", (0,10), (-1,10), "Helvetica-Bold"),
]))
for r in range(1, 10):
bg = LIGHT_ROW if r % 2 == 1 else ALT_ROW
score_tbl.setStyle(TableStyle([("BACKGROUND", (0,r), (-1,r), bg)]))
story.append(score_tbl)
story.append(Spacer(1, 3*mm))
# Compliance legend
legend = [
[Paragraph("<b>Compliance Legend:</b>", sBold),
Paragraph("<font color='#1E8449'><b>≥ 90% Excellent</b></font>", sBold),
Paragraph("<font color='#D35400'><b>75–89% Acceptable</b></font>", sBold),
Paragraph("<font color='#C0392B'><b>< 75% Needs Improvement</b></font>", sBold)],
]
leg_tbl = Table(legend, colWidths=[42*mm, 42*mm, 48*mm, 46*mm])
leg_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), LIGHT_BG),
("BOX", (0,0), (-1,-1), 0.5, TEAL),
("INNERGRID", (0,0), (-1,-1), 0.3, TEAL),
("TOPPADDING", (0,0), (-1,-1), 4),
("BOTTOMPADDING", (0,0), (-1,-1), 4),
("LEFTPADDING", (0,0), (-1,-1), 5),
("ALIGN", (0,0), (-1,-1), "CENTER"),
]))
story.append(leg_tbl)
story.append(Spacer(1, 4*mm))
# ════════════════════════════════════════════════════════════════════════════
# SECTION K — Findings, Observations & Action Plan
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("K", "KEY FINDINGS, OBSERVATIONS & ACTION PLAN"))
story.append(Spacer(1, 2*mm))
obs_data = [
[Paragraph("<b>#</b>", sBold),
Paragraph("<b>Observation / Non-Conformity</b>", sBold),
Paragraph("<b>Section</b>", sBold),
Paragraph("<b>Risk Level</b>", sBold),
Paragraph("<b>Recommended Action</b>", sBold),
Paragraph("<b>Responsible</b>", sBold),
Paragraph("<b>Target Date</b>", sBold)],
]
for i in range(1, 6):
obs_data.append([str(i), "", "", "", "", "", ""])
obs_cw = [8*mm, 55*mm, 18*mm, 18*mm, 42*mm, 22*mm, 17*mm]
obs_tbl = Table(obs_data, colWidths=obs_cw, repeatRows=1)
obs_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), NAVY),
("TEXTCOLOR", (0,0), (-1,0), WHITE),
("FONTSIZE", (0,0), (-1,-1), 8),
("ALIGN", (0,0), (-1,0), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("TOPPADDING", (0,0), (-1,-1), 10),
("BOTTOMPADDING", (0,0), (-1,-1), 10),
("LEFTPADDING", (0,0), (-1,-1), 4),
("BOX", (0,0), (-1,-1), 0.8, NAVY),
("INNERGRID", (0,0), (-1,-1), 0.3, colors.HexColor("#B0C8D0")),
]))
for r in range(1, 6):
bg = LIGHT_ROW if r % 2 == 1 else ALT_ROW
obs_tbl.setStyle(TableStyle([("BACKGROUND", (0,r), (-1,r), bg)]))
story.append(obs_tbl)
story.append(Spacer(1, 4*mm))
# ════════════════════════════════════════════════════════════════════════════
# SIGNATURES
# ════════════════════════════════════════════════════════════════════════════
story.append(section_header("L", "SIGN-OFF"))
story.append(Spacer(1, 2*mm))
sig_data = [
[Paragraph("<b>Auditor / Clinical Pharmacist</b>", sBold),
Paragraph("<b>HOD / Senior Pharmacist</b>", sBold),
Paragraph("<b>Medical Officer / Consultant</b>", sBold),
Paragraph("<b>Quality Manager</b>", sBold)],
["", "", "", ""],
[Paragraph("Signature: _______________", sField),
Paragraph("Signature: _______________", sField),
Paragraph("Signature: _______________", sField),
Paragraph("Signature: _______________", sField)],
[Paragraph("Name: ___________________", sField),
Paragraph("Name: ___________________", sField),
Paragraph("Name: ___________________", sField),
Paragraph("Name: ___________________", sField)],
[Paragraph("Date: ___________________", sField),
Paragraph("Date: ___________________", sField),
Paragraph("Date: ___________________", sField),
Paragraph("Date: ___________________", sField)],
]
sig_cw = [(PAGE_W - 2*MARGIN) / 4] * 4
sig_tbl = Table(sig_data, colWidths=sig_cw)
sig_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), LIGHT_BG),
("BACKGROUND", (0,2), (-1,-1), WHITE),
("BOX", (0,0), (-1,-1), 0.8, TEAL),
("INNERGRID", (0,0), (-1,-1), 0.3, TEAL),
("TOPPADDING", (0,0), (-1,-1), 5),
("BOTTOMPADDING", (0,0), (-1,-1), 5),
("LEFTPADDING", (0,0), (-1,-1), 5),
("ALIGN", (0,0), (-1,0), "CENTER"),
("FONTNAME", (0,0), (-1,0), "Helvetica-Bold"),
("FONTSIZE", (0,0), (-1,-1), 8),
]))
story.append(sig_tbl)
story.append(Spacer(1, 4*mm))
# ── Notes box ────────────────────────────────────────────────────────────────
story.append(Paragraph(
"<b>Additional Notes / Comments:</b>",
sBold
))
notes_box = Table(
[[""] * 1],
colWidths=[PAGE_W - 2*MARGIN],
rowHeights=[28*mm]
)
notes_box.setStyle(TableStyle([
("BOX", (0,0), (-1,-1), 0.8, TEAL),
("BACKGROUND", (0,0), (-1,-1), LIGHT_BG),
]))
story.append(notes_box)
story.append(Spacer(1, 3*mm))
# ── Reference note ───────────────────────────────────────────────────────────
story.append(Paragraph(
"<b>References / Standards:</b> WHO Prescribing Indicators (1993) | ISMP High-Alert Medication List | "
"National List of Essential Medicines (India) | Drugs & Cosmetics Act, 1940 (Schedule H / H1) | "
"JCI / NABH Medication Management Standards | Beers Criteria (AGS 2023) | "
"Antimicrobial Stewardship Guidelines (ICMR / WHO)",
sSmall
))
# ── Build PDF ─────────────────────────────────────────────────────────────────
doc.build(story, onFirstPage=header_footer, onLaterPages=header_footer)
print(f"PDF created: {OUTPUT_PATH}")
cd /tmp/workspace/prescription-audit && python generate_checklist.py 2>&1
ls -lh /tmp/workspace/prescription-audit/Prescription_Audit_Checklist.pdf
Prescription Audit Checklist
PDF Document · PDF
| Section | Topic | Items |
|---|---|---|
| A | Patient Identification | 8 |
| B | Prescriber Information | 7 |
| C | Drug Prescribing Standards | 13 |
| D | Rational Drug Use (WHO Core Indicators) | 7 |
| E | High-Alert & Controlled Drugs | 7 |
| F | Drug Interaction & Safety Screening | 9 |
| G | Antimicrobial Stewardship (AMS) | 8 |
| H | Dispensing & Transcription Accuracy | 8 |
| I | Documentation & Regulatory Compliance | 7 |
| J | Audit Summary Score Table | - |
| K | Key Findings & Action Plan Table | - |
| L | Sign-off block (4 signatories) | - |