Discharge summary perfect

Asking for Preferences
Asking for Preferences
Reading File
Reading File
Running Command

mkdir -p /tmp/workspace/discharge-summary && ls /tmp/workspace/discharge-summary/

Writing File

~/discharge-summary/build_discharge_summary.py

from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
from docx.oxml import OxmlElement

doc = Document()

# ── Page setup (A4) ──────────────────────────────────────────────────────────
section = doc.sections[0]
section.page_width  = Inches(8.27)
section.page_height = Inches(11.69)
section.top_margin    = Inches(0.75)
section.bottom_margin = Inches(0.75)
section.left_margin   = Inches(1.0)
section.right_margin  = Inches(1.0)

# ── Base font ────────────────────────────────────────────────────────────────
normal = doc.styles["Normal"]
normal.font.name = "Calibri"
normal.font.size = Pt(11)

# Customise heading styles
def style_heading(doc, level, size, color_hex="1F3864"):
    h = doc.styles[f"Heading {level}"]
    h.font.name = "Calibri"
    h.font.size = Pt(size)
    h.font.bold = True
    r, g, b = int(color_hex[0:2],16), int(color_hex[2:4],16), int(color_hex[4:6],16)
    h.font.color.rgb = RGBColor(r, g, b)
    h.paragraph_format.space_before = Pt(10)
    h.paragraph_format.space_after  = Pt(4)

style_heading(doc, 1, 16, "1F3864")
style_heading(doc, 2, 13, "2E75B6")
style_heading(doc, 3, 11, "2E75B6")

# ── Helper: shaded table row ─────────────────────────────────────────────────
def set_cell_shading(cell, fill_hex):
    tc   = cell._tc
    tcPr = 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"),  fill_hex)
    tcPr.append(shd)

def set_cell_borders(cell, top=None, bottom=None, left=None, right=None):
    tc   = cell._tc
    tcPr = tc.get_or_add_tcPr()
    tcBorders = OxmlElement("w:tcBorders")
    for side, val in [("top", top), ("bottom", bottom), ("left", left), ("right", right)]:
        if val:
            el = OxmlElement(f"w:{side}")
            el.set(qn("w:val"),  val.get("val","single"))
            el.set(qn("w:sz"),   val.get("sz","4"))
            el.set(qn("w:space"),"0")
            el.set(qn("w:color"),val.get("color","auto"))
            tcBorders.append(el)
    tcPr.append(tcBorders)

def add_field_row(table, label, value_placeholder, label_bg="D6E4F0", row_bg="FFFFFF"):
    row = table.add_row()
    lc  = row.cells[0]
    vc  = row.cells[1]
    lc.width = Inches(2.0)
    vc.width = Inches(4.27)
    set_cell_shading(lc, label_bg)
    set_cell_shading(vc, row_bg)
    lp = lc.paragraphs[0]
    lp.clear()
    run = lp.add_run(label)
    run.bold = True
    run.font.size = Pt(10)
    run.font.color.rgb = RGBColor(0x1F,0x38,0x64)
    vp = vc.paragraphs[0]
    vp.clear()
    vr = vp.add_run(value_placeholder)
    vr.font.size = Pt(11)
    vr.font.color.rgb = RGBColor(0x60,0x60,0x60)
    return row

def section_table(doc, fields, label_bg="D6E4F0"):
    tbl = doc.add_table(rows=0, cols=2)
    tbl.style = "Table Grid"
    tbl.alignment = WD_TABLE_ALIGNMENT.LEFT
    for label, placeholder in fields:
        add_field_row(tbl, label, placeholder, label_bg=label_bg)
    return tbl

def add_section_heading(doc, title, level=2):
    doc.add_heading(title, level=level)

def add_note_box(doc, text):
    """A lightly shaded paragraph acting as an info box."""
    p = doc.add_paragraph()
    pPr = p._p.get_or_add_pPr()
    shd = OxmlElement("w:shd")
    shd.set(qn("w:val"),   "clear")
    shd.set(qn("w:color"), "auto")
    shd.set(qn("w:fill"),  "EBF3FB")
    pPr.append(shd)
    run = p.add_run(text)
    run.italic = True
    run.font.size = Pt(9)
    run.font.color.rgb = RGBColor(0x2E,0x75,0xB6)
    p.paragraph_format.left_indent  = Inches(0.1)
    p.paragraph_format.right_indent = Inches(0.1)
    p.paragraph_format.space_after  = Pt(6)

# ════════════════════════════════════════════════════════════════════════════
# HEADER BANNER
# ════════════════════════════════════════════════════════════════════════════
title_para = doc.add_paragraph()
title_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
title_para.paragraph_format.space_before = Pt(0)
title_para.paragraph_format.space_after  = Pt(2)
tr = title_para.add_run("HOSPITAL NAME / DEPARTMENT")
tr.bold = True
tr.font.size = Pt(18)
tr.font.color.rgb = RGBColor(0x1F,0x38,0x64)
tr.font.name = "Calibri"

subtitle_para = doc.add_paragraph()
subtitle_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
subtitle_para.paragraph_format.space_after = Pt(2)
sr = subtitle_para.add_run("Department of General Medicine / Internal Medicine")
sr.font.size = Pt(11)
sr.font.color.rgb = RGBColor(0x50,0x50,0x50)
sr.font.name = "Calibri"

doc_type_para = doc.add_paragraph()
doc_type_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
doc_type_para.paragraph_format.space_after = Pt(8)
dtr = doc_type_para.add_run("DISCHARGE SUMMARY")
dtr.bold = True
dtr.font.size = Pt(15)
dtr.font.color.rgb = RGBColor(0x2E,0x75,0xB6)
dtr.font.name = "Calibri"

# Horizontal rule (thin table acting as a line)
hr = doc.add_table(rows=1, cols=1)
hr_cell = hr.cell(0, 0)
set_cell_shading(hr_cell, "1F3864")
hr.rows[0].height = Pt(2)
hr_cell.paragraphs[0].clear()
doc.add_paragraph()  # spacer

# ════════════════════════════════════════════════════════════════════════════
# SECTION 1 – PATIENT IDENTIFICATION
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "1. Patient Identification")
section_table(doc, [
    ("Patient Name",         "[Full name]"),
    ("Date of Birth",        "[DD/MM/YYYY]"),
    ("Age / Gender",         "[Age] years   |   [Male / Female / Other]"),
    ("MRN / Hospital ID",    "[Medical Record Number]"),
    ("Address",              "[Street, City, Postcode]"),
    ("Contact Number",       "[Phone / Mobile]"),
    ("Emergency Contact",    "[Name]  –  [Relationship]  –  [Phone]"),
    ("Next of Kin",          "[Name]  –  [Relationship]"),
    ("Insurance / Payer",    "[Insurance provider / Self-pay / Government scheme]"),
])
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 2 – ADMISSION & DISCHARGE DETAILS
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "2. Admission & Discharge Details")
section_table(doc, [
    ("Date of Admission",       "[DD/MM/YYYY]"),
    ("Time of Admission",       "[HH:MM]"),
    ("Date of Discharge",       "[DD/MM/YYYY]"),
    ("Time of Discharge",       "[HH:MM]"),
    ("Length of Stay",          "[X days]"),
    ("Admitting Ward / Unit",   "[Ward name / Bed number]"),
    ("Admitting Physician",     "[Dr. Name]  –  [Designation]"),
    ("Treating Consultant",     "[Dr. Name]  –  [Speciality]"),
    ("Discharge Destination",   "[Home / Transfer to facility / Nursing home / Deceased]"),
    ("Discharge Condition",     "[Stable / Improved / Guarded / Deceased]"),
    ("Mode of Discharge",       "[Self / Against medical advice (AMA) / Transfer / Deceased]"),
])
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 3 – PRESENTING COMPLAINT & HISTORY
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "3. Presenting Complaint & History")

add_section_heading(doc, "3a. Chief Complaint", level=3)
add_note_box(doc, "State the primary reason for admission in the patient's own words or as a brief clinical phrase.")
doc.add_paragraph("[Chief complaint]", style="List Bullet")

add_section_heading(doc, "3b. History of Presenting Illness (HPI)", level=3)
add_note_box(doc, "Chronological narrative: onset, duration, character, severity, associated symptoms, aggravating/relieving factors, prior similar episodes.")
doc.add_paragraph("[Detailed HPI narrative]")

add_section_heading(doc, "3c. Past Medical History (PMH)", level=3)
for item in [
    "[Chronic condition 1 – year of diagnosis]",
    "[Chronic condition 2 – year of diagnosis]",
    "[Previous hospitalisations / surgeries]",
    "[No significant PMH – if applicable]",
]:
    doc.add_paragraph(item, style="List Bullet")

add_section_heading(doc, "3d. Surgical / Procedural History", level=3)
doc.add_paragraph("[Procedure – Year – Hospital]", style="List Bullet")

add_section_heading(doc, "3e. Drug & Allergy History", level=3)
drug_tbl = doc.add_table(rows=1, cols=4)
drug_tbl.style = "Table Grid"
headers = ["Drug / Substance", "Dose & Route", "Duration / Frequency", "Allergy / Reaction"]
hrow = drug_tbl.rows[0]
for i, h in enumerate(headers):
    cell = hrow.cells[i]
    set_cell_shading(cell, "1F3864")
    p = cell.paragraphs[0]
    p.clear()
    run = p.add_run(h)
    run.bold = True
    run.font.color.rgb = RGBColor(0xFF,0xFF,0xFF)
    run.font.size = Pt(10)
for _ in range(3):
    r = drug_tbl.add_row()
    for c in r.cells:
        c.paragraphs[0].add_run("[...]").font.size = Pt(11)
doc.add_paragraph()

add_section_heading(doc, "3f. Family History", level=3)
doc.add_paragraph("[Relevant family history – condition – relation]", style="List Bullet")

add_section_heading(doc, "3g. Social History", level=3)
for item in [
    "Smoking: [Never / Ex-smoker (X pack-years) / Current (X/day)]",
    "Alcohol: [None / Occasional / Regular – X units/week]",
    "Recreational drugs: [None / specify]",
    "Occupation: [specify]",
    "Living situation: [Lives alone / With family / Carer at home]",
    "Functional status pre-admission: [Independent / Needs assistance]",
]:
    doc.add_paragraph(item, style="List Bullet")
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 4 – EXAMINATION FINDINGS ON ADMISSION
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "4. Examination Findings on Admission")

add_section_heading(doc, "4a. Vital Signs", level=3)
vs_tbl = doc.add_table(rows=1, cols=6)
vs_tbl.style = "Table Grid"
vs_headers = ["BP (mmHg)", "HR (bpm)", "RR (/min)", "SpO2 (%)", "Temp (°C)", "GCS"]
vhrow = vs_tbl.rows[0]
for i, h in enumerate(vs_headers):
    c = vhrow.cells[i]
    set_cell_shading(c, "2E75B6")
    p = c.paragraphs[0]
    p.clear()
    run = p.add_run(h)
    run.bold = True
    run.font.color.rgb = RGBColor(0xFF,0xFF,0xFF)
    run.font.size = Pt(9)
vr2 = vs_tbl.add_row()
for c in vr2.cells:
    c.paragraphs[0].add_run("[...]").font.size = Pt(11)
doc.add_paragraph()

add_section_heading(doc, "4b. General Examination", level=3)
for item in [
    "General: [Well / Unwell / Alert / Obtunded / Cachectic / Distressed]",
    "Pallor: [Absent / Present]   Icterus: [Absent / Present]",
    "Cyanosis: [Absent / Present]   Clubbing: [Absent / Present]",
    "Lymphadenopathy: [Absent / Present – specify region]",
    "Oedema: [Absent / Present – pitting/non-pitting, extent]",
]:
    doc.add_paragraph(item, style="List Bullet")

add_section_heading(doc, "4c. Systemic Examination", level=3)
for system in [
    ("Cardiovascular", "Heart sounds: [S1, S2 heard / Murmurs / Added sounds]"),
    ("Respiratory",    "Air entry: [Bilateral / Reduced]  Breath sounds: [Clear / Crepitations / Wheeze]"),
    ("Abdomen",        "[Soft / Tender / Organomegaly / Distension / Bowel sounds]"),
    ("Neurological",   "[Conscious / GCS: E_V_M_ / Focal deficits / Reflexes]"),
    ("Musculoskeletal","[Deformity / Swelling / Range of motion / Tenderness]"),
    ("Skin",           "[Rash / Wounds / Pressure areas / Ulcers]"),
]:
    p = doc.add_paragraph(style="List Bullet")
    run_bold = p.add_run(f"{system[0]}: ")
    run_bold.bold = True
    run_bold.font.size = Pt(11)
    p.add_run(system[1]).font.size = Pt(11)
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 5 – INVESTIGATIONS
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "5. Investigations")

add_section_heading(doc, "5a. Laboratory Results", level=3)
lab_tbl = doc.add_table(rows=1, cols=4)
lab_tbl.style = "Table Grid"
lab_headers = ["Investigation", "Admission Value", "Discharge Value", "Reference Range"]
lhrow = lab_tbl.rows[0]
for i, h in enumerate(lab_headers):
    c = lhrow.cells[i]
    set_cell_shading(c, "1F3864")
    p = c.paragraphs[0]
    p.clear()
    run = p.add_run(h)
    run.bold = True
    run.font.color.rgb = RGBColor(0xFF,0xFF,0xFF)
    run.font.size = Pt(10)
lab_rows = [
    ("Haemoglobin (Hb)", "[X g/dL]", "[X g/dL]", "12–16 g/dL"),
    ("WBC",              "[X ×10³/µL]", "[X ×10³/µL]", "4.5–11 ×10³/µL"),
    ("Platelets",        "[X ×10³/µL]", "[X ×10³/µL]", "150–400 ×10³/µL"),
    ("Sodium (Na+)",     "[X mmol/L]",  "[X mmol/L]",  "135–145 mmol/L"),
    ("Potassium (K+)",   "[X mmol/L]",  "[X mmol/L]",  "3.5–5.0 mmol/L"),
    ("Creatinine",       "[X µmol/L]",  "[X µmol/L]",  "60–110 µmol/L"),
    ("Urea",             "[X mmol/L]",  "[X mmol/L]",  "2.5–6.4 mmol/L"),
    ("Glucose (random)", "[X mmol/L]",  "[X mmol/L]",  "3.9–7.8 mmol/L"),
    ("HbA1c",            "[X%]",        "[X%]",         "<6.5%"),
    ("CRP",              "[X mg/L]",    "[X mg/L]",     "<10 mg/L"),
    ("Liver enzymes (ALT/AST)", "[X U/L]", "[X U/L]", "7–56 U/L"),
    ("Other: [specify]", "[...]",       "[...]",        "[...]"),
]
for lr in lab_rows:
    r = lab_tbl.add_row()
    for i, val in enumerate(lr):
        c = r.cells[i]
        if i % 2 == 0:
            set_cell_shading(c, "EBF3FB")
        c.paragraphs[0].clear()
        rv = c.paragraphs[0].add_run(val)
        rv.font.size = Pt(10)
doc.add_paragraph()

add_section_heading(doc, "5b. Microbiology / Cultures", level=3)
for item in [
    "Blood culture: [No growth / Organism – Sensitivity]",
    "Urine culture: [No growth / Organism – Sensitivity]",
    "Sputum culture: [No growth / Organism – Sensitivity]",
    "COVID-19 / Influenza / Other rapid test: [Negative / Positive]",
]:
    doc.add_paragraph(item, style="List Bullet")

add_section_heading(doc, "5c. Imaging & Special Investigations", level=3)
img_tbl = doc.add_table(rows=1, cols=3)
img_tbl.style = "Table Grid"
img_headers = ["Investigation", "Date", "Key Finding"]
ihrow = img_tbl.rows[0]
for i, h in enumerate(img_headers):
    c = ihrow.cells[i]
    set_cell_shading(c, "2E75B6")
    p = c.paragraphs[0]
    p.clear()
    run = p.add_run(h)
    run.bold = True
    run.font.color.rgb = RGBColor(0xFF,0xFF,0xFF)
    run.font.size = Pt(10)
for inv in [
    ("Chest X-ray (CXR)",         "[DD/MM/YYYY]", "[Findings]"),
    ("ECG",                        "[DD/MM/YYYY]", "[Findings]"),
    ("Echocardiogram",             "[DD/MM/YYYY]", "[Findings]"),
    ("Ultrasound [organ/region]",  "[DD/MM/YYYY]", "[Findings]"),
    ("CT [region]",                "[DD/MM/YYYY]", "[Findings]"),
    ("MRI [region]",               "[DD/MM/YYYY]", "[Findings]"),
    ("Spirometry / PFT",           "[DD/MM/YYYY]", "[Findings]"),
    ("Other: [specify]",           "[DD/MM/YYYY]", "[Findings]"),
]:
    r = img_tbl.add_row()
    for i, v in enumerate(inv):
        c = r.cells[i]
        if i == 0:
            set_cell_shading(c, "EBF3FB")
        c.paragraphs[0].clear()
        c.paragraphs[0].add_run(v).font.size = Pt(10)
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 6 – DIAGNOSIS
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "6. Diagnosis")

add_section_heading(doc, "6a. Primary Diagnosis", level=3)
p = doc.add_paragraph(style="List Number")
run = p.add_run("[Primary diagnosis  –  ICD-10 code if applicable]")
run.bold = True; run.font.size = Pt(11)

add_section_heading(doc, "6b. Secondary / Co-morbid Diagnoses", level=3)
for item in [
    "[Secondary diagnosis 1  –  ICD-10]",
    "[Secondary diagnosis 2  –  ICD-10]",
    "[Pre-existing comorbidity – stable / controlled / worsened]",
]:
    doc.add_paragraph(item, style="List Number")

add_section_heading(doc, "6c. Complications During Admission", level=3)
doc.add_paragraph("[Complication / None]", style="List Bullet")
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 7 – TREATMENT GIVEN DURING ADMISSION
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "7. Treatment During Admission")

add_section_heading(doc, "7a. Medications Administered", level=3)
med_tbl = doc.add_table(rows=1, cols=5)
med_tbl.style = "Table Grid"
med_headers = ["Drug", "Dose", "Route", "Frequency", "Duration / Notes"]
mhrow = med_tbl.rows[0]
for i, h in enumerate(med_headers):
    c = mhrow.cells[i]
    set_cell_shading(c, "1F3864")
    p = c.paragraphs[0]
    p.clear()
    run = p.add_run(h)
    run.bold = True
    run.font.color.rgb = RGBColor(0xFF,0xFF,0xFF)
    run.font.size = Pt(10)
for _ in range(5):
    r = med_tbl.add_row()
    for c in r.cells:
        c.paragraphs[0].add_run("[...]").font.size = Pt(11)
doc.add_paragraph()

add_section_heading(doc, "7b. Procedures / Interventions", level=3)
for item in [
    "[Procedure / Intervention – Date – Operator – Outcome]",
    "[IV access / Central line / Urinary catheter – Date – Removed on]",
    "Transfusions: [Packed RBCs / FFP / Platelets – units – dates]",
    "Oxygen therapy: [Method – flow rate – duration]",
    "Nil by mouth (NBM): [Dates – reason]",
]:
    doc.add_paragraph(item, style="List Bullet")

add_section_heading(doc, "7c. Specialist Consultations", level=3)
for item in [
    "[Speciality – Consultant – Date – Recommendation]",
    "[Physiotherapy / Occupational therapy / Speech therapy / Dietitian / Social work]",
]:
    doc.add_paragraph(item, style="List Bullet")
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 8 – HOSPITAL COURSE & CLINICAL PROGRESS
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "8. Hospital Course & Clinical Progress")
add_note_box(doc, "Summarise the clinical course chronologically: response to treatment, complications encountered, change in management plan, and overall trajectory (improving / deteriorating / stable).")
doc.add_paragraph("[Day 1–2: ...]")
doc.add_paragraph("[Day 3–5: ...]")
doc.add_paragraph("[Day X onward: ...]")
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 9 – CONDITION AT DISCHARGE
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "9. Condition at Discharge")
section_table(doc, [
    ("General condition",   "[Stable / Improved / Guarded]"),
    ("Vital signs at discharge", "BP: [X/X]  HR: [X]  RR: [X]  SpO2: [X%]  Temp: [X°C]"),
    ("Functional status",   "[Independent / Requires assistance – specify]"),
    ("Mobility",            "[Ambulatory / Wheelchair / Bedbound]"),
    ("Diet at discharge",   "[Normal / Soft diet / NG feed / TPN / NBM]"),
    ("Wound / Drain status","[Healed / Open – dressing / Drain removed on]"),
    ("Cognitive status",    "[Intact / Confused / Improved from admission]"),
], label_bg="D6E4F0")
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 10 – DISCHARGE MEDICATIONS
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "10. Discharge Medications")
add_note_box(doc, "List ALL medications to be taken after discharge. Highlight any NEW medications, changed doses, and STOPPED medications clearly.")
dm_tbl = doc.add_table(rows=1, cols=6)
dm_tbl.style = "Table Grid"
dm_headers = ["Drug", "Dose", "Route", "Frequency", "Duration", "New / Continued / Stopped"]
dmhrow = dm_tbl.rows[0]
for i, h in enumerate(dm_headers):
    c = dmhrow.cells[i]
    set_cell_shading(c, "1F3864")
    p = c.paragraphs[0]
    p.clear()
    run = p.add_run(h)
    run.bold = True
    run.font.color.rgb = RGBColor(0xFF,0xFF,0xFF)
    run.font.size = Pt(9)
for _ in range(5):
    r = dm_tbl.add_row()
    for c in r.cells:
        c.paragraphs[0].add_run("[...]").font.size = Pt(10)
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 11 – FOLLOW-UP PLAN
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "11. Follow-Up Plan")
fu_tbl = doc.add_table(rows=1, cols=4)
fu_tbl.style = "Table Grid"
fu_headers = ["Provider / Clinic", "Date / Timeframe", "Location", "Purpose"]
fuhrow = fu_tbl.rows[0]
for i, h in enumerate(fu_headers):
    c = fuhrow.cells[i]
    set_cell_shading(c, "2E75B6")
    p = c.paragraphs[0]
    p.clear()
    run = p.add_run(h)
    run.bold = True
    run.font.color.rgb = RGBColor(0xFF,0xFF,0xFF)
    run.font.size = Pt(10)
for row_data in [
    ("GP / Primary care",       "Within [X] days",  "[Clinic address]", "Review, medication reconciliation"),
    ("[Specialist clinic]",     "[DD/MM/YYYY]",      "[Location]",       "[Purpose]"),
    ("Pathology / Blood tests", "[X] days post-discharge", "[Lab]",     "[Tests to be repeated]"),
    ("Imaging",                 "[Date / timeframe]","[Location]",       "[Type of imaging]"),
]:
    r = fu_tbl.add_row()
    for i, v in enumerate(row_data):
        c = r.cells[i]
        if i == 0:
            set_cell_shading(c, "EBF3FB")
        c.paragraphs[0].clear()
        c.paragraphs[0].add_run(v).font.size = Pt(10)
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 12 – PATIENT EDUCATION & DISCHARGE INSTRUCTIONS
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "12. Patient Education & Discharge Instructions")
for item in [
    "Diagnosis explained to patient and family: [Yes / No / Partially]",
    "Medication counselling provided: [Yes / No]",
    "Diet & lifestyle advice: [Low-salt diet / Diabetic diet / Fluid restriction / Activity restriction]",
    "Wound care instructions: [Yes / Not applicable]",
    "Red flag symptoms – return to ED if: [Chest pain / Breathlessness / Fever >38°C / Bleeding / Worsening symptoms]",
    "Written discharge instructions given: [Yes / No]",
    "Language / interpreter used: [English / specify language / Interpreter arranged]",
    "Patient verbalized understanding: [Yes / No]",
]:
    doc.add_paragraph(item, style="List Bullet")
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 13 – PENDING RESULTS & OUTSTANDING ISSUES
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "13. Pending Results & Outstanding Issues")
add_note_box(doc, "List any results not yet available at time of discharge. GP / follow-up team must review and act on these.")
for item in [
    "[Culture result pending – follow up in X days]",
    "[Histopathology / Biopsy – result expected DD/MM/YYYY]",
    "[Outpatient investigation to be arranged: specify]",
    "[Outstanding referral: specify speciality]",
]:
    doc.add_paragraph(item, style="List Bullet")
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 14 – NOTIFICATIONS & COMMUNICATIONS
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "14. Notifications & Communications")
section_table(doc, [
    ("GP notified",              "[Yes / No / Not applicable]  –  Date: [DD/MM/YYYY]"),
    ("Family / NOK informed",    "[Yes / No]  –  Name: [  ]  –  Date: [DD/MM/YYYY]"),
    ("Transfer letter sent",     "[Yes / No / Not applicable]"),
    ("Reportable disease notification", "[Yes / No – Disease: specify / Not applicable]"),
    ("Medicolegal issues",       "[Yes / No – specify if yes]"),
], label_bg="D6E4F0")
doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# SECTION 15 – CLINICIAN SIGN-OFF
# ════════════════════════════════════════════════════════════════════════════
add_section_heading(doc, "15. Clinician Sign-Off")
sig_tbl = doc.add_table(rows=1, cols=2)
sig_tbl.style = "Table Grid"
sig_tbl.alignment = WD_TABLE_ALIGNMENT.LEFT

left = sig_tbl.cell(0, 0)
right = sig_tbl.cell(0, 1)
set_cell_shading(left,  "F2F7FC")
set_cell_shading(right, "F2F7FC")

for cell, fields in [
    (left, [
        ("Prepared by",       "[Name – Designation – Registration No.]"),
        ("Signature",         "______________________________"),
        ("Date",              "[DD/MM/YYYY]"),
        ("Contact",           "[Direct phone / Pager / Email]"),
    ]),
    (right, [
        ("Reviewed / Countersigned by", "[Consultant Name – Designation]"),
        ("Signature",                   "______________________________"),
        ("Date",                        "[DD/MM/YYYY]"),
        ("Stamp",                       "[Hospital / Department Stamp]"),
    ]),
]:
    for label, value in fields:
        p = cell.add_paragraph()
        rb = p.add_run(f"{label}: ")
        rb.bold = True
        rb.font.size = Pt(10)
        rv = p.add_run(value)
        rv.font.size = Pt(10)
        p.paragraph_format.space_after = Pt(4)

# ── Footer note ───────────────────────────────────────────────────────────
doc.add_paragraph()
footer_p = doc.add_paragraph()
footer_p.alignment = WD_ALIGN_PARAGRAPH.CENTER
fr = footer_p.add_run(
    "CONFIDENTIAL – This document contains protected health information. "
    "Handle in accordance with applicable privacy legislation."
)
fr.italic = True
fr.font.size = Pt(8)
fr.font.color.rgb = RGBColor(0x80,0x80,0x80)

# ── Save ─────────────────────────────────────────────────────────────────────
out_path = "/tmp/workspace/discharge-summary/Discharge_Summary_Template_General_Medicine.docx"
doc.save(out_path)
print(f"Saved: {out_path}")
Running Command

python3 /tmp/workspace/discharge-summary/build_discharge_summary.py

Your perfect discharge summary template is ready!

Discharge Summary Template General Medicine

Word Document · DOCX


Here's what's included across 15 sections:
#SectionWhat's covered
1Patient IdentificationName, DOB, MRN, contacts, insurance
2Admission & Discharge DetailsDates, times, length of stay, ward, consultant, discharge condition
3Presenting Complaint & HistoryHPI, PMH, surgical history, drug/allergy table, family & social history
4Examination on AdmissionVital signs table, general + systemic examination (CVS, Resp, Abdomen, Neuro, MSK, Skin)
5InvestigationsLab results table (with reference ranges), microbiology, imaging & special tests
6DiagnosisPrimary + secondary diagnoses with ICD-10 fields, complications
7Treatment During AdmissionMedications table, procedures/interventions, specialist consultations
8Hospital Course & ProgressChronological narrative field
9Condition at DischargeVitals, functional status, mobility, diet, wound status
10Discharge MedicationsFull med table with New / Continued / Stopped column
11Follow-Up PlanGP, specialist, labs, imaging - with dates and purposes
12Patient EducationCounselling checklist, red flag symptoms, language/interpreter
13Pending ResultsOutstanding investigations and referrals for GP to action
14NotificationsGP notification, NOK, transfer letter, reportable disease
15Clinician Sign-OffPrepared by + countersigned by, with stamp field
Design highlights: colour-coded headers (navy/blue), shaded label columns, a confidentiality footer, and all tables use Word's built-in Table Grid style so formatting stays intact when edited. All placeholder text is in [square brackets] - just click and replace.

Discharge summary perfect

Asking for Preferences
Asking for Preferences
Reading File
Writing File

~/discharge-summary/build_og_discharge_summary.py

from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
from docx.oxml import OxmlElement

doc = Document()

# ── Page setup (A4) ──────────────────────────────────────────────────────────
section = doc.sections[0]
section.page_width   = Inches(8.27)
section.page_height  = Inches(11.69)
section.top_margin    = Inches(0.75)
section.bottom_margin = Inches(0.75)
section.left_margin   = Inches(1.0)
section.right_margin  = Inches(1.0)

# ── Base font ────────────────────────────────────────────────────────────────
normal = doc.styles["Normal"]
normal.font.name = "Calibri"
normal.font.size = Pt(11)

# Theme colours – soft rose/mauve palette for O&G
C_DARK  = "6B2D5E"   # deep plum   – main headings
C_MID   = "A0467E"   # mid magenta – sub-headings / table headers
C_LIGHT = "F5E6F0"   # pale blush  – label column bg
C_ALT   = "FDF2FA"   # very pale   – alternating row / value bg

def style_heading(doc, level, size, color_hex):
    h = doc.styles[f"Heading {level}"]
    h.font.name = "Calibri"
    h.font.size = Pt(size)
    h.font.bold = True
    r, g, b = int(color_hex[0:2],16), int(color_hex[2:4],16), int(color_hex[4:6],16)
    h.font.color.rgb = RGBColor(r, g, b)
    h.paragraph_format.space_before = Pt(10)
    h.paragraph_format.space_after  = Pt(4)

style_heading(doc, 1, 16, C_DARK)
style_heading(doc, 2, 13, C_MID)
style_heading(doc, 3, 11, C_MID)

# ── XML helpers ──────────────────────────────────────────────────────────────
def set_cell_shading(cell, fill_hex):
    tc   = cell._tc
    tcPr = 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"),  fill_hex)
    tcPr.append(shd)

def add_field_row(table, label, placeholder, label_bg=C_LIGHT, val_bg="FFFFFF"):
    row = table.add_row()
    lc, vc = row.cells[0], row.cells[1]
    set_cell_shading(lc, label_bg)
    set_cell_shading(vc, val_bg)
    lp = lc.paragraphs[0]; lp.clear()
    lr = lp.add_run(label); lr.bold = True; lr.font.size = Pt(10)
    r, g, b = int(C_DARK[0:2],16), int(C_DARK[2:4],16), int(C_DARK[4:6],16)
    lr.font.color.rgb = RGBColor(r, g, b)
    vp = vc.paragraphs[0]; vp.clear()
    vr = vp.add_run(placeholder); vr.font.size = Pt(11)
    vr.font.color.rgb = RGBColor(0x60,0x60,0x60)

def section_table(doc, fields):
    tbl = doc.add_table(rows=0, cols=2)
    tbl.style = "Table Grid"
    tbl.alignment = WD_TABLE_ALIGNMENT.LEFT
    for label, ph in fields:
        add_field_row(tbl, label, ph)
    return tbl

def header_row(table, headers, bg=C_DARK):
    row = table.rows[0]
    r2, g2, b2 = int(bg[0:2],16), int(bg[2:4],16), int(bg[4:6],16)
    for i, h in enumerate(headers):
        c = row.cells[i]
        set_cell_shading(c, bg)
        p = c.paragraphs[0]; p.clear()
        run = p.add_run(h); run.bold = True
        run.font.color.rgb = RGBColor(0xFF,0xFF,0xFF)
        run.font.size = Pt(10)

def add_note(doc, text):
    p = doc.add_paragraph()
    pPr = p._p.get_or_add_pPr()
    shd = OxmlElement("w:shd")
    shd.set(qn("w:val"),   "clear")
    shd.set(qn("w:color"), "auto")
    shd.set(qn("w:fill"),  "FEF4FB")
    pPr.append(shd)
    run = p.add_run(text)
    run.italic = True; run.font.size = Pt(9)
    r, g, b = int(C_MID[0:2],16), int(C_MID[2:4],16), int(C_MID[4:6],16)
    run.font.color.rgb = RGBColor(r, g, b)
    p.paragraph_format.left_indent  = Inches(0.1)
    p.paragraph_format.space_after  = Pt(6)

def spacer(doc):
    doc.add_paragraph()

# ════════════════════════════════════════════════════════════════════════════
# HEADER BANNER
# ════════════════════════════════════════════════════════════════════════════
t = doc.add_paragraph(); t.alignment = WD_ALIGN_PARAGRAPH.CENTER
t.paragraph_format.space_before = Pt(0); t.paragraph_format.space_after = Pt(2)
tr = t.add_run("HOSPITAL NAME")
tr.bold = True; tr.font.size = Pt(18); tr.font.name = "Calibri"
tr.font.color.rgb = RGBColor(int(C_DARK[0:2],16), int(C_DARK[2:4],16), int(C_DARK[4:6],16))

s = doc.add_paragraph(); s.alignment = WD_ALIGN_PARAGRAPH.CENTER
s.paragraph_format.space_after = Pt(2)
sr = s.add_run("Department of Obstetrics & Gynaecology")
sr.font.size = Pt(11); sr.font.name = "Calibri"
sr.font.color.rgb = RGBColor(0x50,0x50,0x50)

d = doc.add_paragraph(); d.alignment = WD_ALIGN_PARAGRAPH.CENTER
d.paragraph_format.space_after = Pt(8)
dr = d.add_run("DISCHARGE SUMMARY")
dr.bold = True; dr.font.size = Pt(15); dr.font.name = "Calibri"
dr.font.color.rgb = RGBColor(int(C_MID[0:2],16), int(C_MID[2:4],16), int(C_MID[4:6],16))

# Divider line
hr = doc.add_table(rows=1, cols=1)
set_cell_shading(hr.cell(0,0), C_DARK)
hr.rows[0].height = Pt(2)
hr.cell(0,0).paragraphs[0].clear()
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 1 – PATIENT IDENTIFICATION
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("1. Patient Identification", level=2)
section_table(doc, [
    ("Patient Name",         "[Full name]"),
    ("Date of Birth",        "[DD/MM/YYYY]"),
    ("Age",                  "[Age] years"),
    ("MRN / Hospital ID",    "[Medical Record Number]"),
    ("Address",              "[Street, City, Postcode]"),
    ("Contact Number",       "[Phone / Mobile]"),
    ("Emergency Contact",    "[Name]  –  [Relationship]  –  [Phone]"),
    ("Next of Kin / Partner","[Name]  –  [Relationship]  –  [Phone]"),
    ("Insurance / Payer",    "[Insurance provider / Self-pay / Government scheme]"),
    ("GP / Primary Care",    "[GP Name]  –  [Practice Name]  –  [Phone / Fax]"),
])
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 2 – ADMISSION & DISCHARGE DETAILS
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("2. Admission & Discharge Details", level=2)
section_table(doc, [
    ("Date of Admission",         "[DD/MM/YYYY]"),
    ("Time of Admission",         "[HH:MM]"),
    ("Date of Discharge",         "[DD/MM/YYYY]"),
    ("Time of Discharge",         "[HH:MM]"),
    ("Length of Stay",            "[X days]"),
    ("Admitting Ward / Unit",     "[Antenatal / Postnatal / Gynaecology / Labour ward / HDU]"),
    ("Admitting Consultant",      "[Dr. Name]  –  [Designation]"),
    ("Treating Consultant",       "[Dr. Name]  –  [O&G Speciality: MFM / Gyn-Onc / General O&G]"),
    ("Discharge Destination",     "[Home / Transfer / Tertiary centre / Midwifery-led unit]"),
    ("Discharge Condition",       "[Stable / Improved / Guarded]"),
    ("Mode of Discharge",         "[Self / Transfer / Against medical advice (AMA)]"),
])
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 3 – OBSTETRIC / GYNAECOLOGICAL HISTORY
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("3. Obstetric & Gynaecological History", level=2)

doc.add_heading("3a. Current Pregnancy (if applicable)", level=3)
add_note(doc, "Complete this section for obstetric admissions. Leave N/A for purely gynaecological admissions.")
section_table(doc, [
    ("Gravida / Para",            "[G  P  + ]  (miscarriages / ectopics / terminations)"),
    ("Gestational Age on Admission", "[X weeks + X days]  (by LMP / dating scan)"),
    ("LMP",                       "[DD/MM/YYYY]"),
    ("EDD",                       "[DD/MM/YYYY]  (by scan / LMP)"),
    ("Dating Scan",               "[DD/MM/YYYY]  –  CRL / BPD / [X weeks + X days]"),
    ("Fetal Number",              "[Singleton / Twin / Higher-order multiples]"),
    ("Chorionicity (if multiple)","[MCDA / MCMA / DCDA / DCMA]"),
    ("Booking Blood Group",       "[A+ / B+ / O+ / AB+ / A- / B- / O- / AB-]"),
    ("Rubella Immunity",          "[Immune / Non-immune / Not tested]"),
    ("Antenatal Care",            "[Shared care: GP + hospital / Hospital only / Midwifery-led / Unbooked]"),
])
spacer(doc)

doc.add_heading("3b. Past Obstetric History", level=3)
ob_tbl = doc.add_table(rows=1, cols=7)
ob_tbl.style = "Table Grid"
header_row(ob_tbl, ["Pregnancy #", "Year", "GA at Delivery", "Mode of Delivery", "Birth Weight", "Outcome", "Complications"], bg=C_DARK)
for _ in range(3):
    r = ob_tbl.add_row()
    for c in r.cells:
        c.paragraphs[0].add_run("[...]").font.size = Pt(10)
spacer(doc)

doc.add_heading("3c. Gynaecological History", level=3)
section_table(doc, [
    ("Menstrual History",         "[Regular / Irregular – cycle length – LMP]"),
    ("Contraception",             "[Current method / None]"),
    ("Last Cervical Smear / Pap", "[Date]  –  [Result]"),
    ("Previous Gynaecological Surgeries", "[Procedure – Year – Indication]"),
    ("STI History",               "[None / specify]"),
    ("Fertility Treatment",       "[None / IVF / IUI / Clomid – cycle number]"),
])
spacer(doc)

doc.add_heading("3d. Past Medical & Surgical History", level=3)
for item in [
    "[Medical condition 1 – year – current status]",
    "[Medical condition 2 – year – current status]",
    "[Previous non-O&G surgeries – year – hospital]",
]:
    doc.add_paragraph(item, style="List Bullet")
spacer(doc)

doc.add_heading("3e. Drug & Allergy History", level=3)
da_tbl = doc.add_table(rows=1, cols=4)
da_tbl.style = "Table Grid"
header_row(da_tbl, ["Drug / Substance", "Dose & Route", "Frequency", "Allergy / Reaction"], bg=C_MID)
for _ in range(4):
    r = da_tbl.add_row()
    for c in r.cells:
        c.paragraphs[0].add_run("[...]").font.size = Pt(11)
spacer(doc)

doc.add_heading("3f. Family & Social History", level=3)
for item in [
    "Family history: [Obstetric complications / Hereditary conditions / Congenital anomalies]",
    "Smoking: [Never / Ex / Current – X/day]",
    "Alcohol: [None / Occasional / Regular – X units/week]",
    "Recreational drugs: [None / specify]",
    "Occupation: [specify]",
    "Social support: [Partner / Family / Lives alone / Social services involvement]",
    "Domestic violence screen: [Screened / Declined / Concerns documented]",
]:
    doc.add_paragraph(item, style="List Bullet")
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 4 – PRESENTING COMPLAINT & REASON FOR ADMISSION
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("4. Presenting Complaint & Reason for Admission", level=2)
add_note(doc, "Tick one or more. Add a brief clinical narrative below.")

reason_tbl = doc.add_table(rows=0, cols=4)
reason_tbl.style = "Table Grid"
reasons = [
    ("☐ Labour (spontaneous)", "☐ Induction of labour",      "☐ Elective LSCS",            "☐ Emergency LSCS"),
    ("☐ Pre-eclampsia / HTD",  "☐ PPROM / PROM",              "☐ Antepartum haemorrhage",   "☐ Postpartum haemorrhage"),
    ("☐ Fetal distress",       "☐ Preterm labour",            "☐ Reduced fetal movements",  "☐ Hyperemesis gravidarum"),
    ("☐ Ectopic pregnancy",    "☐ Miscarriage / EPAS",        "☐ Gynaecological surgery",   "☐ Pelvic pain"),
    ("☐ Ovarian cyst",         "☐ Abnormal uterine bleeding", "☐ Sepsis / Infection",        "☐ Other: [specify]"),
]
for row_data in reasons:
    row = reason_tbl.add_row()
    for i, val in enumerate(row_data):
        row.cells[i].paragraphs[0].add_run(val).font.size = Pt(10)
spacer(doc)

doc.add_heading("Presenting History (Narrative)", level=3)
add_note(doc, "Chronological account: onset, duration, severity, associated symptoms, relevant context.")
doc.add_paragraph("[Detailed narrative of presenting complaint]")
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 5 – EXAMINATION FINDINGS ON ADMISSION
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("5. Examination Findings on Admission", level=2)

doc.add_heading("5a. Vital Signs", level=3)
vs_tbl = doc.add_table(rows=1, cols=6)
vs_tbl.style = "Table Grid"
header_row(vs_tbl, ["BP (mmHg)", "HR (bpm)", "RR (/min)", "SpO2 (%)", "Temp (°C)", "GCS / AVPU"], bg=C_MID)
vr = vs_tbl.add_row()
for c in vr.cells:
    c.paragraphs[0].add_run("[...]").font.size = Pt(11)
spacer(doc)

doc.add_heading("5b. General & Obstetric Examination", level=3)
for item in [
    "General appearance: [Well / Unwell / Distressed / Comfortable]",
    "BMI at booking / admission: [X kg/m²]",
    "Pallor / Icterus / Oedema (facial, hands, legs): [specify]",
    "Uterine size / fundal height: [X weeks / X cm]",
    "Fetal presentation: [Cephalic / Breech / Transverse / Oblique]",
    "Engagement: [Engaged / Floating – X/5 palpable]",
    "Fetal heart rate on auscultation: [X bpm / CTG performed – see findings]",
    "Liquor / Membranes: [Intact / Ruptured – colour / volume]",
    "Cervical assessment: [Closed / X cm dilated / X% effaced / Station X / Bishop score X]",
    "Vaginal loss: [None / Bleeding / Discharge – specify]",
]:
    doc.add_paragraph(item, style="List Bullet")

doc.add_heading("5c. Systemic Examination", level=3)
for system, detail in [
    ("Cardiovascular",   "Heart sounds [S1 S2] / Murmurs / Oedema"),
    ("Respiratory",      "Air entry / Breath sounds / Wheeze / Crepitations"),
    ("Abdomen",          "Uterine tenderness / Rebound / Guarding / Bowel sounds"),
    ("Neurological",     "Conscious / Reflexes (hyperreflexia?) / Clonus / Visual disturbance"),
]:
    p = doc.add_paragraph(style="List Bullet")
    rb = p.add_run(f"{system}: "); rb.bold = True; rb.font.size = Pt(11)
    p.add_run(f"[{detail}]").font.size = Pt(11)
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 6 – INVESTIGATIONS
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("6. Investigations", level=2)

doc.add_heading("6a. Antenatal Bloods / Booking Bloods", level=3)
ab_tbl = doc.add_table(rows=1, cols=3)
ab_tbl.style = "Table Grid"
header_row(ab_tbl, ["Investigation", "Result / Date", "Notes / Action Taken"], bg=C_DARK)
for inv in [
    ("Blood group & antibody screen",  "[Result]",  "[Action]"),
    ("FBC",                            "[Result]",  "[Action]"),
    ("HbA1c / GCT / OGTT",            "[Result]",  "[Action]"),
    ("Rubella IgG",                    "[Result]",  "[Action]"),
    ("Syphilis serology (VDRL/TPPA)",  "[Result]",  "[Action]"),
    ("HIV serology",                   "[Result]",  "[Action]"),
    ("Hepatitis B (HBsAg)",            "[Result]",  "[Action]"),
    ("Hepatitis C",                    "[Result]",  "[Action]"),
    ("Varicella IgG",                  "[Result]",  "[Action]"),
    ("Thyroid function (TSH/T4)",      "[Result]",  "[Action]"),
    ("GBS screening",                  "[Result]",  "[Action]"),
    ("Other: [specify]",               "[Result]",  "[Action]"),
]:
    r = ab_tbl.add_row()
    for i, v in enumerate(inv):
        c = r.cells[i]
        if i == 0: set_cell_shading(c, C_ALT)
        c.paragraphs[0].clear()
        c.paragraphs[0].add_run(v).font.size = Pt(10)
spacer(doc)

doc.add_heading("6b. Admission Labs (with Discharge Comparison)", level=3)
lab_tbl = doc.add_table(rows=1, cols=4)
lab_tbl.style = "Table Grid"
header_row(lab_tbl, ["Test", "Admission Value", "Discharge Value", "Reference Range"], bg=C_DARK)
for row_data in [
    ("Haemoglobin",      "[X g/dL]",    "[X g/dL]",    "12–16 g/dL"),
    ("WBC",              "[X ×10³/µL]", "[X ×10³/µL]", "4.5–11 ×10³/µL"),
    ("Platelets",        "[X ×10³/µL]", "[X ×10³/µL]", "150–400 ×10³/µL"),
    ("Sodium",           "[X mmol/L]",  "[X mmol/L]",  "135–145 mmol/L"),
    ("Potassium",        "[X mmol/L]",  "[X mmol/L]",  "3.5–5.0 mmol/L"),
    ("Creatinine",       "[X µmol/L]",  "[X µmol/L]",  "45–90 µmol/L (preg)"),
    ("Urea",             "[X mmol/L]",  "[X mmol/L]",  "2.5–6.4 mmol/L"),
    ("LFTs (ALT/AST/Bili)", "[X U/L]", "[X U/L]",     "Varies"),
    ("LDH",              "[X U/L]",     "[X U/L]",     "120–246 U/L"),
    ("Uric acid",        "[X mmol/L]",  "[X mmol/L]",  "Varies"),
    ("Coagulation (PT/APTT)", "[X s]",  "[X s]",       "Varies"),
    ("CRP",              "[X mg/L]",    "[X mg/L]",    "<10 mg/L"),
    ("Urinalysis / PCR", "[Result]",    "[Result]",    "Negative"),
    ("Other: [specify]", "[...]",       "[...]",       "[...]"),
]:
    r = lab_tbl.add_row()
    for i, v in enumerate(row_data):
        c = r.cells[i]
        if i % 2 == 0: set_cell_shading(c, C_ALT)
        c.paragraphs[0].clear()
        c.paragraphs[0].add_run(v).font.size = Pt(10)
spacer(doc)

doc.add_heading("6c. Imaging & Monitoring", level=3)
img_tbl = doc.add_table(rows=1, cols=3)
img_tbl.style = "Table Grid"
header_row(img_tbl, ["Investigation", "Date", "Key Findings"], bg=C_MID)
for inv in [
    ("Obstetric ultrasound – dating scan",        "[Date]", "[CRL / EDD / Anomalies]"),
    ("Obstetric ultrasound – anatomy scan",       "[Date]", "[Findings]"),
    ("Obstetric ultrasound – growth scan",        "[Date]", "[EFW / AC / HC / Liquor / Placenta]"),
    ("Doppler studies (umbilical / MCA / uterine)","[Date]","[PI / RI / End-diastolic flow]"),
    ("Cardiotocography (CTG)",                    "[Date]", "[Reactive / Non-reactive / Category]"),
    ("Fetal scalp pH / lactate",                  "[Date]", "[pH / Lactate value]"),
    ("Chest X-ray",                               "[Date]", "[Findings]"),
    ("Pelvic / Abdominal USS",                    "[Date]", "[Findings]"),
    ("CT / MRI [region]",                         "[Date]", "[Findings – indication for radiation exposure documented if CT]"),
    ("Colposcopy / Hysteroscopy / Laparoscopy",   "[Date]", "[Findings]"),
    ("Other: [specify]",                          "[Date]", "[Findings]"),
]:
    r = img_tbl.add_row()
    for i, v in enumerate(inv):
        c = r.cells[i]
        if i == 0: set_cell_shading(c, C_ALT)
        c.paragraphs[0].clear()
        c.paragraphs[0].add_run(v).font.size = Pt(10)
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 7 – DIAGNOSIS
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("7. Diagnosis", level=2)

doc.add_heading("7a. Primary Diagnosis", level=3)
p = doc.add_paragraph(style="List Number")
r2 = p.add_run("[Primary diagnosis  –  ICD-10 code]"); r2.bold = True; r2.font.size = Pt(11)

doc.add_heading("7b. Secondary / Co-existing Diagnoses", level=3)
for item in [
    "[Secondary diagnosis  –  ICD-10]",
    "[Pre-existing comorbidity – status during admission]",
    "[Fetal / Neonatal diagnosis – ICD-10 (if applicable)]",
]:
    doc.add_paragraph(item, style="List Number")

doc.add_heading("7c. Complications During Admission", level=3)
doc.add_paragraph("[Complication / None]", style="List Bullet")
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 8 – LABOUR, DELIVERY & NEONATAL OUTCOME (obstetric)
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("8. Labour, Delivery & Neonatal Outcome", level=2)
add_note(doc, "Complete for all obstetric deliveries. Mark N/A for gynaecological-only admissions.")

doc.add_heading("8a. Labour Details", level=3)
section_table(doc, [
    ("Onset of labour",             "[Spontaneous / Induced – method / Pre-labour LSCS]"),
    ("IOL indication & method",     "[Post-dates / Medical / Surgical – Prostaglandin / ARM / Oxytocin]"),
    ("Duration of labour",          "1st stage: [X hrs]   2nd stage: [X mins]   3rd stage: [X mins]"),
    ("Analgesia",                   "[Epidural / CSE / Pethidine / Entonox / None]"),
    ("Membranes",                   "[SROM at X cm / AROM at X cm / Intact]  –  Liquor: [Clear / Meconium grade / Bloodstained]"),
    ("Intrapartum CTG",             "[Reassuring / Category II / Category III – action taken]"),
    ("Oxytocin augmentation",       "[Yes – rate / No]"),
    ("Group B Strep prophylaxis",   "[Given / Not indicated / Declined]"),
])
spacer(doc)

doc.add_heading("8b. Mode of Delivery", level=3)
section_table(doc, [
    ("Mode of delivery",            "[SVD / Forceps / Ventouse / Emergency LSCS / Elective LSCS]"),
    ("Indication (if operative)",   "[Fetal distress / Failure to progress / Malpresentation / Maternal request]"),
    ("Date & time of delivery",     "[DD/MM/YYYY  –  HH:MM]"),
    ("Operator",                    "[Dr. / Midwife Name]  –  [Grade]"),
    ("Perineum (vaginal delivery)",  "[Intact / 1st / 2nd / 3rd / 4th degree tear / Episiotomy – repair method]"),
    ("LSCS incision type",          "[Pfannenstiel / Lower segment / Classical / Not applicable]"),
    ("LSCS uterine incision",       "[Lower segment transverse / Classical / Not applicable]"),
    ("EBL (estimated blood loss)",  "[X mL]"),
    ("Placental delivery",          "[Complete / Incomplete – retained products / Manual removal]"),
    ("Cord blood gases",            "Art pH: [X]  Base excess: [X]   Ven pH: [X]"),
])
spacer(doc)

doc.add_heading("8c. Neonatal Outcome", level=3)
neo_tbl = doc.add_table(rows=1, cols=5)
neo_tbl.style = "Table Grid"
header_row(neo_tbl, ["Parameter", "Baby 1", "Baby 2 (if applicable)", "Baby 3 (if applicable)", "Notes"], bg=C_DARK)
for param in [
    "Sex",
    "Birth weight (g)",
    "Gestational age at delivery",
    "APGAR score (1 min / 5 min)",
    "Resuscitation required",
    "Paediatrician attendance",
    "Admission to NICU / SCN",
    "Feeding at discharge",
    "Cord blood group",
    "Vitamin K given",
    "Newborn hearing screen",
    "Metabolic / PKU screen",
    "Discharge with mother",
]:
    r = neo_tbl.add_row()
    r.cells[0].paragraphs[0].add_run(param).font.size = Pt(10)
    set_cell_shading(r.cells[0], C_LIGHT)
    for c in r.cells[1:]:
        c.paragraphs[0].add_run("[...]").font.size = Pt(10)
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 9 – TREATMENT DURING ADMISSION
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("9. Treatment During Admission", level=2)

doc.add_heading("9a. Medications Administered", level=3)
med_tbl = doc.add_table(rows=1, cols=5)
med_tbl.style = "Table Grid"
header_row(med_tbl, ["Drug", "Dose", "Route", "Frequency", "Duration / Notes"], bg=C_DARK)
for _ in range(6):
    r = med_tbl.add_row()
    for c in r.cells:
        c.paragraphs[0].add_run("[...]").font.size = Pt(11)
spacer(doc)

doc.add_heading("9b. Procedures / Interventions", level=3)
for item in [
    "IV access / Catheterisation: [Date – removed on]",
    "Blood transfusion: [Packed RBCs – X units / FFP / Platelets – indication]",
    "Magnesium sulphate: [Loading dose / Maintenance – indication: eclampsia / neuroprotection]",
    "Corticosteroids for fetal lung maturity: [Drug – doses given – dates]",
    "Anti-D immunoglobulin: [Dose – given on – indication]",
    "Thromboprophylaxis: [LMWH – drug – dose – commenced on]",
    "Uterotonics: [Oxytocin / Ergometrine / Carboprost / Misoprostol – indication]",
    "Cerclage / Pessary: [Placed / Removed – date]",
    "Other procedure: [specify]",
]:
    doc.add_paragraph(item, style="List Bullet")

doc.add_heading("9c. Specialist Consultations", level=3)
for item in [
    "[Specialty – Consultant – Date – Recommendation]",
    "MFM / Perinatology: [Recommendation]",
    "Anaesthetics: [Type – plan discussed]",
    "Haematology: [specify]",
    "Neonatology / Paediatrics: [specify]",
    "Physiotherapy / Pelvic floor: [specify]",
    "Social work / Lactation consultant: [specify]",
]:
    doc.add_paragraph(item, style="List Bullet")
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 10 – HOSPITAL COURSE & CLINICAL PROGRESS
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("10. Hospital Course & Clinical Progress", level=2)
add_note(doc, "Summarise chronologically: response to treatment, complications, change of management plan, trajectory.")
doc.add_paragraph("[Day 1: ...]")
doc.add_paragraph("[Day 2–3: ...]")
doc.add_paragraph("[Day X onward: ...]")
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 11 – CONDITION AT DISCHARGE
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("11. Condition at Discharge", level=2)
section_table(doc, [
    ("General condition",           "[Stable / Improved / Guarded]"),
    ("Vital signs at discharge",    "BP: [X/X]  HR: [X]  Temp: [X°C]  SpO2: [X%]"),
    ("Lochia / Wound",              "Lochia: [Normal / Offensive / Heavy]  Wound: [Healing well / Opened / Dressed]"),
    ("Uterine involution",          "[Well-involuted / Tender / Boggy – at level of umbilicus / below]"),
    ("Breastfeeding / Feeding",     "[Breastfeeding established / Mixed / Formula / Not breastfeeding – reason]"),
    ("Urinary / Bowel function",    "[Voiding well / Catheter removed / Constipation – managed]"),
    ("Mobility",                    "[Ambulatory / Requires assistance / Limited]"),
    ("Mood / Mental state",         "[Stable / EPDS score: X / Referred – Baby blues / PND concerns]"),
    ("Contraception counselled",    "[Yes – method discussed / Deferred to GP]"),
    ("Thromboprophylaxis plan",     "[LMWH – duration / Compression stockings / No longer required]"),
])
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 12 – DISCHARGE MEDICATIONS
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("12. Discharge Medications", level=2)
add_note(doc, "List ALL medications. Highlight NEW, CHANGED DOSE, and STOPPED medications. Include medications safe in breastfeeding if applicable.")
dm_tbl = doc.add_table(rows=1, cols=6)
dm_tbl.style = "Table Grid"
header_row(dm_tbl, ["Drug", "Dose", "Route", "Frequency", "Duration", "New / Continued / Stopped"], bg=C_DARK)
for _ in range(6):
    r = dm_tbl.add_row()
    for c in r.cells:
        c.paragraphs[0].add_run("[...]").font.size = Pt(10)
doc.add_paragraph()
for item in [
    "Iron supplementation: [Ferrous sulfate / dose / duration – if anaemia]",
    "Folic acid: [5 mg / 0.4 mg – duration]",
    "Aspirin 150 mg nocte: [Yes / No – pre-eclampsia prophylaxis until X weeks]",
    "LMWH (thromboprophylaxis): [Drug – dose – duration – stop date: DD/MM/YYYY]",
    "Analgesia: [Paracetamol / Ibuprofen / Codeine – as required / regular – duration]",
    "Anti-D immunoglobulin: [Completed / To be arranged by GP – dose / date]",
]:
    doc.add_paragraph(item, style="List Bullet")
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 13 – FOLLOW-UP PLAN
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("13. Follow-Up Plan", level=2)
fu_tbl = doc.add_table(rows=1, cols=4)
fu_tbl.style = "Table Grid"
header_row(fu_tbl, ["Provider / Clinic", "Date / Timeframe", "Location", "Purpose"], bg=C_MID)
for row_data in [
    ("GP",                           "Within [X] days",          "[Practice]",         "Wound check, BP review, medication reconciliation, contraception"),
    ("Obstetric / O&G clinic",       "[DD/MM/YYYY]",             "[Hospital]",         "[Specify: 6-week postnatal / high-risk review]"),
    ("Midwife / community midwife",  "Daily for [X] days",       "[Home / clinic]",    "Postnatal checks, breastfeeding support"),
    ("Maternal foetal medicine (MFM)","[Date / timeframe]",      "[Hospital]",         "[Indication: GDM, HTD, multiple pregnancy, etc.]"),
    ("Paediatrician / NICU",         "[Date]",                   "[Hospital]",         "[Neonatal follow-up]"),
    ("Pathology / Blood tests",      "[X days post-discharge]",  "[Lab]",              "[Repeat FBC / iron / TFTs / LFTs – specify]"),
    ("Anaesthetic review",           "[Date if applicable]",     "[Hospital]",         "[Post-spinal headache / difficult airway follow-up]"),
    ("Mental health / PNDA",         "[Date if applicable]",     "[GP / clinic]",      "[EPDS follow-up / Perinatal mental health referral]"),
    ("Imaging",                      "[Date / timeframe]",       "[Radiology]",        "[Specify: pelvic USS, wound review USS]"),
]:
    r = fu_tbl.add_row()
    for i, v in enumerate(row_data):
        c = r.cells[i]
        if i == 0: set_cell_shading(c, C_ALT)
        c.paragraphs[0].clear()
        c.paragraphs[0].add_run(v).font.size = Pt(10)
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 14 – PATIENT EDUCATION & DISCHARGE INSTRUCTIONS
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("14. Patient Education & Discharge Instructions", level=2)
for item in [
    "Diagnosis and management explained to patient (and partner): [Yes / No / Partially]",
    "Medication counselling (including safety in breastfeeding): [Yes / No]",
    "Wound care instructions (LSCS / perineal repair): [Yes / Not applicable]",
    "Pelvic floor exercises: [Advised / Physiotherapy referral made]",
    "Activity restrictions: [No heavy lifting for X weeks / Driving: X weeks / Return to work: X weeks]",
    "Sexual intercourse: [Advised to wait X weeks]",
    "Contraception: [Counselled – method: specify / Deferred to GP]",
    "Breastfeeding support resources provided: [Yes / No]",
    "Newborn care instructions: [Provided / Referred to MCHN]",
    "Red flag symptoms – return to ED if: [Heavy bleeding / Fever >38°C / Wound breakdown / Severe headache / Visual changes / Chest pain / Leg pain/swelling / Reduced fetal movements (if ongoing pregnancy)]",
    "Postnatal depression information: [Provided / EPDS planned at GP visit]",
    "Written discharge instructions given: [Yes / No]",
    "Language / interpreter used: [English / Specify / Interpreter present]",
    "Patient verbalized understanding: [Yes / No]",
]:
    doc.add_paragraph(item, style="List Bullet")
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 15 – PENDING RESULTS & OUTSTANDING ISSUES
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("15. Pending Results & Outstanding Issues", level=2)
add_note(doc, "GP and community team MUST review and act on these items.")
for item in [
    "[Culture / sensitivity result – expected DD/MM/YYYY]",
    "[Histopathology / placenta – expected DD/MM/YYYY]",
    "[Neonatal screening result – expected DD/MM/YYYY]",
    "[Genetic / chromosomal result (e.g. amniocentesis) – expected date]",
    "[Outstanding referral: specify speciality]",
    "[Outpatient investigation to be arranged: specify]",
]:
    doc.add_paragraph(item, style="List Bullet")
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 16 – NOTIFICATIONS & COMMUNICATIONS
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("16. Notifications & Communications", level=2)
section_table(doc, [
    ("GP notified",                    "[Yes / No]  –  Date: [DD/MM/YYYY]  –  Method: [Fax / Letter / Electronic]"),
    ("Midwife / MCHN notified",        "[Yes / No]  –  Date: [DD/MM/YYYY]"),
    ("Paediatrician / NICU notified",  "[Yes / No / Not applicable]"),
    ("Social services notified",       "[Yes / No / Not applicable – reason if yes]"),
    ("Stillbirth / perinatal loss notification", "[Yes / No / Not applicable – Coroner / Registry]"),
    ("Reportable disease notification","[Yes / No – specify disease if yes]"),
    ("Birth registered",               "[Yes / Pending – parents advised]"),
    ("Medicolegal / Incident report",  "[Yes / No – specify if yes]"),
    ("Transfer letter sent",           "[Yes / No / Not applicable]"),
])
spacer(doc)

# ════════════════════════════════════════════════════════════════════════════
# SECTION 17 – CLINICIAN SIGN-OFF
# ════════════════════════════════════════════════════════════════════════════
doc.add_heading("17. Clinician Sign-Off", level=2)
sig_tbl = doc.add_table(rows=1, cols=2)
sig_tbl.style = "Table Grid"

left  = sig_tbl.cell(0, 0)
right = sig_tbl.cell(0, 1)
set_cell_shading(left,  "FDF2FA")
set_cell_shading(right, "FDF2FA")

for cell, fields in [
    (left, [
        ("Prepared by",       "[Name – Designation – Registration No.]"),
        ("Signature",         "______________________________"),
        ("Date & Time",       "[DD/MM/YYYY  –  HH:MM]"),
        ("Contact",           "[Direct phone / Pager / Email]"),
    ]),
    (right, [
        ("Reviewed / Countersigned by", "[Consultant Name – O&G Designation]"),
        ("Signature",                   "______________________________"),
        ("Date",                        "[DD/MM/YYYY]"),
        ("Hospital / Dept Stamp",       "[Stamp here]"),
    ]),
]:
    for label, value in fields:
        p = cell.add_paragraph()
        rb = p.add_run(f"{label}: "); rb.bold = True; rb.font.size = Pt(10)
        rv = p.add_run(value); rv.font.size = Pt(10)
        p.paragraph_format.space_after = Pt(4)

# ── Confidentiality footer ────────────────────────────────────────────────
spacer(doc)
fp = doc.add_paragraph(); fp.alignment = WD_ALIGN_PARAGRAPH.CENTER
fr = fp.add_run(
    "CONFIDENTIAL – Contains protected health information for mother and/or neonate. "
    "Handle in accordance with applicable privacy legislation."
)
fr.italic = True; fr.font.size = Pt(8)
fr.font.color.rgb = RGBColor(0x80,0x80,0x80)

# ── Save ─────────────────────────────────────────────────────────────────────
out_path = "/tmp/workspace/discharge-summary/Discharge_Summary_OandG.docx"
doc.save(out_path)
print(f"Saved: {out_path}")
Running Command

python3 /tmp/workspace/discharge-summary/build_og_discharge_summary.py

Your O&G discharge summary template is ready!

Discharge Summary OandG

Word Document · DOCX


Here's what's packed across 17 sections, with O&G-specific detail throughout:
#SectionKey O&G-specific content
1Patient IdentificationGP details, partner/NOK contacts
2Admission & Discharge DetailsWard type (antenatal / postnatal / labour / gynaecology / HDU)
3Obstetric & Gynaecological HistoryG/P, EDD, LMP, chorionicity, booking bloods, past obstetric table, menstrual/contraception/smear history
4Presenting ComplaintTick-box grid covering 20 common O&G reasons for admission
5Examination on AdmissionFundal height, presentation, engagement, FHR, liquor, cervical assessment, Bishop score
6InvestigationsAntenatal/booking bloods (rubella, HIV, HBsAg, GBS, etc.), admission labs with pregnancy reference ranges, obstetric USS, Dopplers, CTG
7DiagnosisPrimary + secondary + fetal/neonatal diagnoses with ICD-10 fields
8Labour, Delivery & Neonatal OutcomeLabour details, IOL method, CTG category, mode of delivery, EBL, cord gases, APGAR table, neonatal outcome table
9Treatment During AdmissionMedications, MgSO4, corticosteroids, anti-D, LMWH, uterotonics, cerclage
10Hospital CourseChronological narrative
11Condition at DischargeLochia, involution, breastfeeding, mood/EPDS, thromboprophylaxis plan
12Discharge MedicationsFull table + specific O&G items (iron, folic acid, aspirin prophylaxis, anti-D)
13Follow-Up PlanGP, midwife, O&G clinic, MFM, NICU, anaesthetics, PNDA
14Patient EducationWound care, pelvic floor, activity/driving/sex restrictions, contraception, red flags, PND info
15Pending ResultsCultures, histopathology, neonatal screening, genetic results
16NotificationsGP, midwife, MCHN, social services, stillbirth/perinatal loss notification, birth registration
17Clinician Sign-OffPrepared by + consultant countersignature with stamp
Design: deep plum/rose colour scheme (appropriate for the specialty), shaded label columns, all tables grid-formatted, confidentiality footer. All fields are [square bracket] placeholders - click and replace.
This is a shared conversation. Sign in to Orris to start your own chat.