How to write doctors order/advise for fluid correction of SBO patient
small bowel obstruction fluid resuscitation doctor orders IV fluid management
1. Admit to: Surgical Ward / HDU (depending on severity)
2. Diagnosis: Small Bowel Obstruction
3. Condition: Guarded
4. Activity: Bed rest
5. Vital signs: Every 1-2 hours (BP, HR, RR, SpO2, Temperature)
6. Strict input/output chart - hourly urine output monitoring
7. Insert urinary catheter (Foley) - target urine output ≥0.5 mL/kg/hr
8. NPO (Nil Per Oral) - absolutely nothing by mouth
9. Insert large-bore NGT (16-18 Fr) - confirm placement
10. NGT to continuous low-wall suction OR free drainage
11. Chart NGT output every 2-4 hours (volume + character)
12. Replace NGT losses: mL for mL with NS + KCl 20 mEq/L
every 4-6 hours, guided by electrolytes
NGT decompression reduces vomiting, prevents aspiration, decreases bowel distension, and lowers risk during induction of anesthesia. - Maingot's Abdominal Operations, p. 620
13. IV Access: Two large-bore peripheral IVs (18G or larger)
OR central venous line if hemodynamically unstable
14. IV FLUID BOLUS:
Normal Saline 0.9% (NS) 500-1000 mL IV STAT
- OR Lactated Ringer's 500-1000 mL IV STAT
- Repeat bolus as needed to restore hemodynamic stability
- Target: MAP >65 mmHg, HR <100 bpm
Initial vigorous crystalloid resuscitation is the most important first step. Patients often present with profound volume losses and may require large amounts of isotonic crystalloid (NS or LR). Colloids (albumin, hetastarch) have NO role. - Maingot's Abdominal Operations, p. 620
15. After initial bolus and hemodynamic stability:
Maintenance: NS 0.9% + KCl 20 mEq/L at 125-150 mL/hr
(Adjust rate based on UO, clinical status, and ongoing losses)
- If vomiting has been prolonged → high risk of
hypokalemic hypochloremic metabolic alkalosis
- In that case prefer: NS 0.9% + KCl (not LR, which
has no chloride replacement benefit in alkalosis)
16. Potassium replacement:
- Start ONLY after adequate urine output is confirmed
(UO ≥0.5 mL/kg/hr or urine output has resumed)
- KCl 20-40 mEq in 250 mL NS over 2-4 hours IV
- Target serum K⁺ ≥3.5 mEq/L
- Do NOT exceed 20 mEq/hr peripheral, 40 mEq/hr central
17. Correct hypomagnesemia if present (MgSO4 1-2 g IV)
- Magnesium is required for refractory hypokalemia correction
18. Correct hypochloremia with NS (preferred fluid)
- Metabolic alkalosis will resolve with Cl replacement
19. Blood:
- CBC with differential
- BMP / CMP: Na, K, Cl, CO2, BUN, Cr, glucose
- Serum lactate (strangulation marker)
- LFTs
- Serum amylase/lipase
- PT/INR, aPTT
- Blood group and screen (crossmatch 2 units if surgery likely)
- ABG if respiratory compromise or hemodynamic instability
20. Imaging (if not done):
- Plain AXR (supine + erect) STAT
- CT Abdomen-Pelvis WITH IV contrast (preferred)
- Identifies transition point, ischemia, closed-loop obstruction
21. ECG (baseline, especially before potassium replacement)
22. Analgesia:
- Morphine 2-4 mg IV q4h PRN (adequate analgesia does NOT
mask peritonitis and should not be withheld)
- OR Ketorolac 15-30 mg IV q6h (if renal function normal)
23. Antiemetics:
- Ondansetron 4-8 mg IV q6-8h PRN nausea/vomiting
24. DVT Prophylaxis:
- Enoxaparin 40 mg SC once daily (start after surgical
clearance, hold if surgery imminent)
- TED stockings / intermittent pneumatic compression
25. Antibiotics:
- NOT routinely indicated for uncomplicated SBO
- GIVE if strangulation suspected or surgery planned:
Cefazolin 2 g IV within 60 min of incision
(Add Metronidazole 500 mg IV if gross contamination)
- Broad-spectrum (e.g., Pip-Tazo 3.375 g IV q6h) if
peritonitis/perforation suspected
Broad-spectrum antibiotics are not indicated for uncomplicated, non-ischemic SBO being managed conservatively. - Schwartz's Principles of Surgery, 11th ed.
26. Reassess fluid status every 2-4 hours:
- Urine output ≥0.5 mL/kg/hr (adequate resuscitation)
- Capillary refill, HR, BP, mental status
- Repeat electrolytes in 4-6 hours after replacement
- Repeat lactate at 4-6 hours (rising lactate = ischemia)
27. If hemodynamically unstable or poor response:
- Consider central line / CVP monitoring
- ICU/HDU transfer
- Urgent surgical consult for exploratory laparotomy
| Problem | Order |
|---|---|
| Volume depletion | NS or LR 500-1000 mL bolus, repeat as needed |
| Maintenance | NS 0.9% + KCl 20 mEq/L at 125-150 mL/hr |
| Hypokalemia | KCl 20-40 mEq IV after confirming UO |
| Hypochloremic alkalosis | NS 0.9% (chloride-rich), avoid LR |
| Ongoing NGT losses | Replace mL for mL with NS + 20 mEq KCl/L |
| Bowel decompression | Large-bore NGT to suction |
| Monitor adequacy | Foley catheter, hourly urine output |
Create a printable ICU/ward order sheet template I can use daily
mkdir -p /home/daytona/workspace/sbo-order-sheet && ls /home/daytona/workspace/s…
~/sbo-order-sheet/generate_sbo_orders.py
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm, cm
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.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
OUTPUT = "/home/daytona/workspace/sbo-order-sheet/SBO_Order_Sheet.pdf"
PAGE_W, PAGE_H = A4
MARGIN = 15 * mm
# ── Colour palette ─────────────────────────────────────────────────────────
NAVY = colors.HexColor("#1a3a5c")
TEAL = colors.HexColor("#2196A6")
LTBLUE = colors.HexColor("#dceef5")
GRAY = colors.HexColor("#f2f4f6")
DKGRAY = colors.HexColor("#555555")
RED = colors.HexColor("#c0392b")
ORANGE = colors.HexColor("#e67e22")
GREEN = colors.HexColor("#1e8449")
WHITE = colors.white
BLACK = colors.black
# ── Styles ──────────────────────────────────────────────────────────────────
base = getSampleStyleSheet()
def style(name, parent="Normal", **kw):
s = ParagraphStyle(name, parent=base[parent], **kw)
return s
sTitle = style("sTitle", fontSize=16, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_CENTER, leading=20)
sSubtitle = style("sSubtitle", fontSize=9, textColor=WHITE, fontName="Helvetica",
alignment=TA_CENTER, leading=12)
sSectionHdr = style("sSectionHdr", fontSize=9, textColor=WHITE, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=11)
sLabel = style("sLabel", fontSize=7.5, textColor=NAVY, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=10)
sBody = style("sBody", fontSize=7.5, textColor=BLACK, fontName="Helvetica",
alignment=TA_LEFT, leading=10)
sSmall = style("sSmall", fontSize=6.5, textColor=DKGRAY,fontName="Helvetica",
alignment=TA_LEFT, leading=9)
sWarning = style("sWarning", fontSize=7.5, textColor=RED, fontName="Helvetica-Bold",
alignment=TA_LEFT, leading=10)
sNote = style("sNote", fontSize=7, textColor=DKGRAY,fontName="Helvetica-Oblique",
alignment=TA_LEFT, leading=9)
sCentered = style("sCentered", fontSize=7.5, textColor=BLACK, fontName="Helvetica",
alignment=TA_CENTER, leading=10)
CW = PAGE_W - 2 * MARGIN # content width
# ── Helper: section banner ──────────────────────────────────────────────────
def banner(num, title, color=NAVY):
data = [[Paragraph(f"<b>{num}. {title}</b>", sSectionHdr)]]
t = Table(data, colWidths=[CW])
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), color),
("TOPPADDING", (0,0), (-1,-1), 3),
("BOTTOMPADDING",(0,0),(-1,-1), 3),
("LEFTPADDING", (0,0), (-1,-1), 6),
]))
return t
# ── Helper: checkbox row ────────────────────────────────────────────────────
CHK = "☐"
def chk_row(items, cols=1):
"""items = list of (label, detail) tuples"""
rows = []
for label, detail in items:
lbl_text = f"<b>{label}</b>" if label else ""
det_text = detail or ""
rows.append([
Paragraph(CHK, sBody),
Paragraph(lbl_text, sLabel),
Paragraph(det_text, sBody),
])
cw = [5*mm, 38*mm, CW - 43*mm]
t = Table(rows, colWidths=cw, repeatRows=0)
t.setStyle(TableStyle([
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 1.5),
("BOTTOMPADDING", (0,0), (-1,-1), 1.5),
("LEFTPADDING", (0,0), (-1,-1), 2),
("RIGHTPADDING", (0,0), (-1,-1), 2),
("LINEBELOW", (0,-1), (-1,-1), 0.3, colors.HexColor("#dddddd")),
]))
return t
def chk_row_bg(items, bg=GRAY):
rows = []
for i, (label, detail) in enumerate(items):
lbl_text = f"<b>{label}</b>" if label else ""
det_text = detail or ""
rows.append([
Paragraph(CHK, sBody),
Paragraph(lbl_text, sLabel),
Paragraph(det_text, sBody),
])
cw = [5*mm, 38*mm, CW - 43*mm]
t = Table(rows, colWidths=cw)
t.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,-1), bg),
("VALIGN", (0,0), (-1,-1), "TOP"),
("TOPPADDING", (0,0), (-1,-1), 1.5),
("BOTTOMPADDING", (0,0), (-1,-1), 1.5),
("LEFTPADDING", (0,0), (-1,-1), 2),
("RIGHTPADDING", (0,0), (-1,-1), 2),
("LINEBELOW", (0,-1), (-1,-1), 0.3, colors.HexColor("#cccccc")),
]))
return t
# ── Helper: write line ──────────────────────────────────────────────────────
def write_line(label, width=60*mm):
line = "_" * 55
data = [[Paragraph(f"<b>{label}:</b>", sLabel), Paragraph(line, sBody)]]
cw = [40*mm, CW - 40*mm]
t = Table(data, colWidths=cw)
t.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1), "BOTTOM"),
("TOPPADDING", (0,0),(-1,-1), 1),
("BOTTOMPADDING", (0,0),(-1,-1), 1),
("LEFTPADDING", (0,0),(-1,-1), 2),
]))
return t
def write_lines_row(*pairs):
"""pairs = (label, width_mm) alternating"""
row = []
cws = []
for label, w in pairs:
row.append(Paragraph(f"<b>{label}:</b> {'_'*int(w/2)}", sBody))
cws.append(w * mm)
t = Table([row], colWidths=cws)
t.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1), "BOTTOM"),
("TOPPADDING", (0,0),(-1,-1), 1),
("BOTTOMPADDING", (0,0),(-1,-1), 1),
("LEFTPADDING", (0,0),(-1,-1), 2),
]))
return t
# ───────────────────────────────────────────────────────────────────────────
# BUILD DOCUMENT
# ───────────────────────────────────────────────────────────────────────────
def build():
doc = SimpleDocTemplate(
OUTPUT,
pagesize=A4,
leftMargin=MARGIN, rightMargin=MARGIN,
topMargin=MARGIN, bottomMargin=12*mm,
title="SBO Fluid Correction Order Sheet",
author="Orris Clinical Tools",
)
story = []
# ════════════════════════════════════════════════════════════
# HEADER BLOCK
# ════════════════════════════════════════════════════════════
header_data = [[
Paragraph("SMALL BOWEL OBSTRUCTION", sTitle),
Paragraph("FLUID CORRECTION & MANAGEMENT ORDER SHEET", sSubtitle),
]]
header = Table([[
Paragraph("SMALL BOWEL OBSTRUCTION<br/>"
"<font size='9'>FLUID CORRECTION & MANAGEMENT ORDER SHEET</font>",
sTitle),
]], colWidths=[CW])
header.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), NAVY),
("TOPPADDING", (0,0),(-1,-1), 6),
("BOTTOMPADDING", (0,0),(-1,-1), 6),
("LEFTPADDING", (0,0),(-1,-1), 8),
("ROUNDEDCORNERS", [4]),
]))
story.append(header)
story.append(Spacer(1, 3*mm))
# ── PATIENT INFO ────────────────────────────────────────────
info_data = [
[
Paragraph("<b>Patient Name:</b> " + "_"*32, sBody),
Paragraph("<b>MRN / IP No:</b> " + "_"*20, sBody),
Paragraph("<b>Date:</b> " + "_"*14, sBody),
],
[
Paragraph("<b>Age:</b> ____ <b>Sex:</b> ____ <b>Wt:</b> ____ kg", sBody),
Paragraph("<b>Ward / Bed:</b> " + "_"*20, sBody),
Paragraph("<b>Time:</b> " + "_"*14, sBody),
],
[
Paragraph("<b>Admitting Surgeon:</b> " + "_"*25, sBody),
Paragraph("<b>Diagnosis:</b> SBO — ☐ Partial ☐ Complete", sBody),
Paragraph("<b>Allergy:</b> " + "_"*14, sBody),
],
]
info_tbl = Table(info_data, colWidths=[CW*0.42, CW*0.36, CW*0.22])
info_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), GRAY),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#cccccc")),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
story.append(info_tbl)
story.append(Spacer(1, 3*mm))
# ════════════════════════════════════════════════════════════
# SECTION 1 — ADMISSION & MONITORING
# ════════════════════════════════════════════════════════════
story.append(banner("1", "ADMISSION & MONITORING"))
story.append(chk_row([
("NPO", "Nil per oral — absolutely nothing by mouth"),
("Admit to", "☐ Ward ☐ HDU ☐ ICU — Bed: _________"),
("Activity", "Bed rest"),
("Vital signs", "Every ____ hr: BP, HR, RR, SpO₂, Temperature, GCS"),
("Foley catheter", "Insert urinary catheter — strict hourly urine output chart"),
("UO target", "≥ 0.5 mL/kg/hr (Patient weight: ____ kg → min UO: ____ mL/hr)"),
("Fluid balance", "Strict I&O chart every 4 hr — running total 24 hr balance"),
("Weight", "Daily morning weight (if feasible)"),
]))
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# SECTION 2 — NGT DECOMPRESSION
# ════════════════════════════════════════════════════════════
story.append(banner("2", "NASOGASTRIC TUBE (NGT) DECOMPRESSION", color=TEAL))
story.append(chk_row([
("Insert NGT", "Large-bore NGT (16–18 Fr) — confirm placement (CXR or auscultation)"),
("Suction", "☐ Continuous low-wall suction ☐ Free drainage to bag"),
("Chart NGT output", "Record volume + character every 2–4 hr"),
("NGT replacement", "Replace mL-for-mL losses with NS 0.9% + KCl 20 mEq/L every ___hr"),
("NGT care", "Flush NGT with 20 mL NS every 4 hr to maintain patency"),
]))
story.append(chk_row_bg([
("", Paragraph(
"⚠ NGT decompression reduces vomiting, prevents aspiration, and relieves distension. "
"Do NOT remove until bowel function returns (flatus/stool) and output <200 mL/day.",
sNote)),
], bg=colors.HexColor("#fff8e1")))
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# SECTION 3 — IV ACCESS & FLUID RESUSCITATION
# ════════════════════════════════════════════════════════════
story.append(banner("3", "IV ACCESS & FLUID RESUSCITATION"))
# Sub-header A
acol = colors.HexColor("#2c6e9e")
sub_a = Table([[Paragraph(" A. ACUTE RESUSCITATION (First 1–2 hours)", sSectionHdr)]],
colWidths=[CW])
sub_a.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), acol),
("TOPPADDING",(0,0),(-1,-1), 2), ("BOTTOMPADDING",(0,0),(-1,-1), 2),
("LEFTPADDING",(0,0),(-1,-1), 6),
]))
story.append(sub_a)
story.append(chk_row([
("IV Access", "Two large-bore peripheral IVs (≥18G) OR central line if haemodynamically unstable"),
("Fluid Bolus", "☐ NS 0.9% ☐ Lactated Ringer's _____ mL IV OVER _____ min → REPEAT PRN"),
("Bolus target", "MAP ≥ 65 mmHg | HR < 100 bpm | UO ≥ 0.5 mL/kg/hr"),
("No colloids", "Albumin / hetastarch are NOT indicated in SBO resuscitation"),
]))
# Sub-header B
sub_b = Table([[Paragraph(" B. MAINTENANCE & REPLACEMENT FLUIDS (After stabilisation)", sSectionHdr)]],
colWidths=[CW])
sub_b.setStyle(TableStyle([
("BACKGROUND",(0,0),(-1,-1), acol),
("TOPPADDING",(0,0),(-1,-1), 2), ("BOTTOMPADDING",(0,0),(-1,-1), 2),
("LEFTPADDING",(0,0),(-1,-1), 6),
]))
story.append(sub_b)
fluid_rows = [
[Paragraph("<b>Fluid</b>", sLabel),
Paragraph("<b>Rate</b>", sLabel),
Paragraph("<b>Duration / Notes</b>", sLabel)],
[Paragraph("☐ NS 0.9% + KCl 20 mEq/L", sBody),
Paragraph("_____ mL/hr", sBody),
Paragraph("Standard maintenance — adjust to UO", sBody)],
[Paragraph("☐ Lactated Ringer's (LR)", sBody),
Paragraph("_____ mL/hr", sBody),
Paragraph("Use if no prolonged vomiting / no alkalosis", sBody)],
[Paragraph("☐ NS 0.9% (plain) + KCl additive", sBody),
Paragraph("_____ mL/hr", sBody),
Paragraph("Preferred if hypochloraemic alkalosis present", sBody)],
[Paragraph("☐ NGT loss replacement", sBody),
Paragraph("mL for mL", sBody),
Paragraph("NS 0.9% + KCl 20 mEq/L — replace every ___hr", sBody)],
]
ftbl = Table(fluid_rows, colWidths=[CW*0.38, CW*0.18, CW*0.44])
ftbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), LTBLUE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#bbbbbb")),
("TOPPADDING", (0,0),(-1,-1), 2.5),
("BOTTOMPADDING", (0,0),(-1,-1), 2.5),
("LEFTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GRAY]),
]))
story.append(ftbl)
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# SECTION 4 — ELECTROLYTE CORRECTION
# ════════════════════════════════════════════════════════════
story.append(banner("4", "ELECTROLYTE CORRECTION", color=colors.HexColor("#1e6e4a")))
story.append(chk_row_bg([
("", Paragraph(
"⚠ Start potassium replacement ONLY after confirming adequate urine output (≥0.5 mL/kg/hr). "
"Never replace K⁺ in an anuric/oliguric patient without senior review.",
sWarning)),
], bg=colors.HexColor("#fdecea")))
elec_rows = [
[Paragraph("<b>Electrolyte</b>", sLabel),
Paragraph("<b>Typical deficit in SBO</b>", sLabel),
Paragraph("<b>Replacement order</b>", sLabel)],
[Paragraph("Potassium (K⁺)", sBody),
Paragraph("Low (↓ from vomiting)", sBody),
Paragraph("KCl 20–40 mEq in 250 mL NS over 2–4 hr IV\n"
"Max rate: 20 mEq/hr peripheral / 40 mEq/hr central\n"
"Target K⁺ ≥ 3.5 mEq/L\n"
"☐ Oral KCl _____ mEq BD (if NGT clamped)", sSmall)],
[Paragraph("Chloride (Cl⁻)", sBody),
Paragraph("Low — hypochloraemic metabolic alkalosis", sBody),
Paragraph("Correct with NS 0.9% (chloride-rich)\n"
"Alkalosis resolves as Cl⁻ and volume restored", sSmall)],
[Paragraph("Magnesium (Mg²⁺)", sBody),
Paragraph("Low (if prolonged poor intake)", sBody),
Paragraph("MgSO₄ 1–2 g in 100 mL NS over 30–60 min IV\n"
"Required for refractory hypokalaemia correction", sSmall)],
[Paragraph("Sodium (Na⁺)", sBody),
Paragraph("May be low or normal", sBody),
Paragraph("Correct slowly if hyponatraemic\n"
"≤ 8–10 mEq/L per 24 hr to avoid osmotic demyelination", sSmall)],
]
etbl = Table(elec_rows, colWidths=[CW*0.18, CW*0.28, CW*0.54])
etbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), colors.HexColor("#c8e6c9")),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#bbbbbb")),
("TOPPADDING", (0,0),(-1,-1), 2.5),
("BOTTOMPADDING", (0,0),(-1,-1), 2.5),
("LEFTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "TOP"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GRAY]),
]))
story.append(etbl)
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# SECTION 5 — INVESTIGATIONS
# ════════════════════════════════════════════════════════════
story.append(banner("5", "INVESTIGATIONS", color=colors.HexColor("#5d3e8e")))
# Two-column checklist
inv_left = [
("CBC + differential", ""),
("BMP/CMP", "Na, K, Cl, CO₂, BUN, Creatinine, Glucose"),
("Serum lactate", "STAT — repeat at 4–6 hr (↑ = ischaemia)"),
("LFTs + Amylase/Lipase", ""),
("Coagulation", "PT / INR / aPTT"),
("Blood group & screen", "Crossmatch 2 units if surgery likely"),
("ABG", "If haemodynamic instability or SpO₂ <94%"),
]
inv_right = [
("AXR Erect + Supine", "STAT — air-fluid levels, bowel calibre"),
("CT Abd-Pelvis + IV contrast", "PREFERRED — transition point, ischaemia, closed-loop"),
("Ultrasound abdomen", "If CT unavailable / pregnant patient"),
("ECG", "Baseline before K⁺ replacement"),
("Urine R/E + C/S", ""),
("Repeat electrolytes", "4–6 hr after replacement commenced"),
("Repeat lactate", "At 4 hr — if rising → urgent surgical review"),
]
def inv_col(items):
rows = []
for label, detail in items:
d = f" — {detail}" if detail else ""
rows.append([Paragraph(CHK, sBody),
Paragraph(f"<b>{label}</b>{d}", sSmall)])
t = Table(rows, colWidths=[5*mm, (CW/2)-8*mm])
t.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1), "TOP"),
("TOPPADDING", (0,0),(-1,-1), 1.5),
("BOTTOMPADDING", (0,0),(-1,-1), 1.5),
("LEFTPADDING", (0,0),(-1,-1), 2),
]))
return t
inv_tbl = Table([[inv_col(inv_left), inv_col(inv_right)]], colWidths=[CW/2, CW/2])
inv_tbl.setStyle(TableStyle([
("VALIGN", (0,0),(-1,-1), "TOP"),
("LINEAFTER", (0,0),(0,-1), 0.4, colors.HexColor("#cccccc")),
]))
story.append(inv_tbl)
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# SECTION 6 — MEDICATIONS
# ════════════════════════════════════════════════════════════
story.append(banner("6", "MEDICATIONS", color=colors.HexColor("#7b3f00")))
story.append(chk_row([
("Analgesia", "Morphine 2–4 mg IV q4h PRN OR Ketorolac 15–30 mg IV q6h (if renal fn normal)"),
("Antiemetic", "Ondansetron 4–8 mg IV q6–8h PRN nausea/vomiting"),
("PPI / H2", "Pantoprazole 40 mg IV OD (stress ulcer prophylaxis)"),
("DVT Prophylaxis","Enoxaparin 40 mg SC OD — START after surgical clearance (hold if surgery imminent)"),
(" Mechanical", "TED stockings + Intermittent pneumatic compression (IPC)"),
]))
story.append(chk_row_bg([
("Antibiotics", "NOT routinely indicated for uncomplicated SBO"),
("Give if strangulation / surgery:", "Cefazolin 2 g IV within 60 min of incision ± Metronidazole 500 mg IV"),
("If peritonitis / perforation:", "Pip-Tazo 4.5 g IV q8h OR Meropenem 1 g IV q8h"),
], bg=colors.HexColor("#fff3e0")))
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# SECTION 7 — MONITORING TARGETS & REASSESSMENT
# ════════════════════════════════════════════════════════════
story.append(banner("7", "MONITORING TARGETS & REASSESSMENT SCHEDULE"))
target_data = [
[Paragraph("<b>Parameter</b>", sLabel),
Paragraph("<b>Target</b>", sLabel),
Paragraph("<b>Frequency</b>", sLabel),
Paragraph("<b>Action if not met</b>", sLabel)],
[Paragraph("Urine output", sBody),
Paragraph("≥ 0.5 mL/kg/hr", sBody),
Paragraph("Hourly", sBody),
Paragraph("500 mL fluid bolus → reassess; if no response → senior review", sSmall)],
[Paragraph("Mean arterial pressure", sBody),
Paragraph("≥ 65 mmHg", sBody),
Paragraph("1–2 hrly", sBody),
Paragraph("Fluid bolus; consider vasopressors if unresponsive", sSmall)],
[Paragraph("Heart rate", sBody),
Paragraph("< 100 bpm", sBody),
Paragraph("1–2 hrly", sBody),
Paragraph("Review fluid status, rule out sepsis/ischaemia", sSmall)],
[Paragraph("Serum K⁺", sBody),
Paragraph("3.5–5.0 mEq/L", sBody),
Paragraph("4–6 hrly", sBody),
Paragraph("Replace as per Section 4 protocol", sSmall)],
[Paragraph("Serum lactate", sBody),
Paragraph("< 2.0 mmol/L", sBody),
Paragraph("At admission + 4–6 hr", sBody),
Paragraph("Rising lactate → URGENT surgical review for ischaemia", sSmall)],
[Paragraph("NGT output", sBody),
Paragraph("Chart; replace mL:mL", sBody),
Paragraph("Every 2–4 hr", sBody),
Paragraph("Replace with NS + KCl 20 mEq/L", sSmall)],
[Paragraph("Abdominal exam", sBody),
Paragraph("No peritonism", sBody),
Paragraph("Every 4–6 hr", sBody),
Paragraph("New peritonism → immediate surgical consult", sSmall)],
[Paragraph("Electrolytes repeat", sBody),
Paragraph("Within normal range", sBody),
Paragraph("4–6 hr post replacement", sBody),
Paragraph("Adjust replacement as needed", sSmall)],
]
ttbl = Table(target_data, colWidths=[CW*0.2, CW*0.17, CW*0.17, CW*0.46])
ttbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), LTBLUE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#bbbbbb")),
("TOPPADDING", (0,0),(-1,-1), 2),
("BOTTOMPADDING", (0,0),(-1,-1), 2),
("LEFTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "TOP"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GRAY]),
]))
story.append(ttbl)
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# SECTION 8 — ESCALATION CRITERIA
# ════════════════════════════════════════════════════════════
story.append(banner("8", "SURGICAL ESCALATION — CALL SURGEON IMMEDIATELY IF ANY:", color=RED))
esc_data = [
[Paragraph("☐ Signs of peritonitis (rigid abdomen, involuntary guarding, rebound tenderness)", sBody),
Paragraph("☐ Rising serum lactate > 2 mmol/L despite adequate resuscitation", sBody)],
[Paragraph("☐ Fever + progressive leukocytosis (WBC > 15,000)", sBody),
Paragraph("☐ CT evidence: closed-loop obstruction, pneumatosis intestinalis, free air", sBody)],
[Paragraph("☐ Haemodynamic instability not responding to 2 L fluid resuscitation", sBody),
Paragraph("☐ No clinical improvement after 48 hr conservative management", sBody)],
[Paragraph("☐ Complete SBO confirmed on CT (no gas in colon/rectum)", sBody),
Paragraph("☐ Strangulation suspected (constant severe pain, tachycardia, fever)", sBody)],
]
etbl2 = Table(esc_data, colWidths=[CW/2, CW/2])
etbl2.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), colors.HexColor("#fdecea")),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#e8b4b0")),
("TOPPADDING", (0,0),(-1,-1), 2.5),
("BOTTOMPADDING", (0,0),(-1,-1), 2.5),
("LEFTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "TOP"),
]))
story.append(etbl2)
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# SECTION 9 — QUICK REFERENCE
# ════════════════════════════════════════════════════════════
story.append(banner("9", "QUICK REFERENCE — FLUID SELECTION GUIDE", color=colors.HexColor("#2c6e9e")))
qr_data = [
[Paragraph("<b>Clinical Scenario</b>", sLabel),
Paragraph("<b>Preferred Fluid</b>", sLabel),
Paragraph("<b>Additive / Rate</b>", sLabel)],
[Paragraph("Acute volume depletion (initial)", sBody),
Paragraph("NS 0.9% OR Lactated Ringer's", sBody),
Paragraph("500–1000 mL bolus; repeat PRN", sSmall)],
[Paragraph("Maintenance (haemodynamically stable)", sBody),
Paragraph("NS 0.9%", sBody),
Paragraph("+ KCl 20 mEq/L @ 100–150 mL/hr", sSmall)],
[Paragraph("Prolonged vomiting / hypochloraemic alkalosis", sBody),
Paragraph("NS 0.9% (NOT LR)", sBody),
Paragraph("+ KCl; LR lacks chloride — avoid", sSmall)],
[Paragraph("Replace ongoing NGT losses", sBody),
Paragraph("NS 0.9%", sBody),
Paragraph("+ KCl 20 mEq/L; mL-for-mL q4–6h", sSmall)],
[Paragraph("Hypokalaemia correction", sBody),
Paragraph("KCl 20–40 mEq in 250 mL NS", sBody),
Paragraph("Over 2–4 hr IV; max 20 mEq/hr peripheral", sSmall)],
[Paragraph("Hypomagnesaemia (refractory hypokalaemia)", sBody),
Paragraph("MgSO₄ 1–2 g in 100 mL NS", sBody),
Paragraph("Over 30–60 min IV", sSmall)],
[Paragraph("Haemodynamic instability + poor response", sBody),
Paragraph("Escalate — ICU / CVP monitoring", sBody),
Paragraph("Consider vasopressors; surgical review", sSmall)],
]
qrtbl = Table(qr_data, colWidths=[CW*0.35, CW*0.32, CW*0.33])
qrtbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,0), LTBLUE),
("FONTNAME", (0,0),(-1,0), "Helvetica-Bold"),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#bbbbbb")),
("TOPPADDING", (0,0),(-1,-1), 2.5),
("BOTTOMPADDING", (0,0),(-1,-1), 2.5),
("LEFTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "TOP"),
("ROWBACKGROUNDS",(0,1),(-1,-1), [WHITE, GRAY]),
]))
story.append(qrtbl)
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# SIGNATURES
# ════════════════════════════════════════════════════════════
story.append(banner("10", "ORDERS WRITTEN BY", color=DKGRAY))
sig_data = [
[
Paragraph("<b>Ordering Physician:</b> " + "_"*28, sBody),
Paragraph("<b>Designation:</b> " + "_"*20, sBody),
Paragraph("<b>Date/Time:</b> " + "_"*16, sBody),
],
[
Paragraph("<b>Signature:</b> " + "_"*30, sBody),
Paragraph("<b>Contact / Bleep:</b> " + "_"*18, sBody),
Paragraph("<b>Countersign:</b> " + "_"*16, sBody),
],
]
sig_tbl = Table(sig_data, colWidths=[CW*0.42, CW*0.33, CW*0.25])
sig_tbl.setStyle(TableStyle([
("BACKGROUND", (0,0),(-1,-1), GRAY),
("GRID", (0,0),(-1,-1), 0.4, colors.HexColor("#cccccc")),
("TOPPADDING", (0,0),(-1,-1), 3),
("BOTTOMPADDING", (0,0),(-1,-1), 3),
("LEFTPADDING", (0,0),(-1,-1), 4),
("VALIGN", (0,0),(-1,-1), "MIDDLE"),
]))
story.append(sig_tbl)
story.append(Spacer(1, 2*mm))
# ════════════════════════════════════════════════════════════
# FOOTER NOTE
# ════════════════════════════════════════════════════════════
story.append(HRFlowable(width=CW, thickness=0.5, color=TEAL))
story.append(Spacer(1, 1*mm))
footer_txt = (
"Based on: Maingot's Abdominal Operations | Schwartz's Principles of Surgery 11e | "
"Sabiston Textbook of Surgery | Mulholland & Greenfield's Surgery 7e | StatPearls SBO Guidelines. "
"This template is a clinical aid — all orders must be reviewed and signed by a licensed physician. "
"Doses must be adjusted for patient weight, renal function, and clinical status."
)
story.append(Paragraph(footer_txt, sNote))
# ── BUILD ──────────────────────────────────────────────────
doc.build(story)
print(f"PDF saved to: {OUTPUT}")
if __name__ == "__main__":
build()
cd /home/daytona/workspace/sbo-order-sheet && python generate_sbo_orders.py 2>&1
~/sbo-order-sheet/generate_sbo_orders.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/sbo-order-sheet/generate_sbo_orders.py'
~/sbo-order-sheet/generate_sbo_orders.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/sbo-order-sheet/generate_sbo_orders.py'
~/sbo-order-sheet/generate_sbo_orders.py
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/sbo-order-sheet/generate_sbo_orders.py'
cd /home/daytona/workspace/sbo-order-sheet && python generate_sbo_orders.py 2>&1
ls -lh /home/daytona/workspace/sbo-order-sheet/SBO_Order_Sheet.pdf && python3 -c…
SBO Order Sheet
PDF Document · PDF
| Section | Contents |
|---|---|
| Patient Info Header | Name, MRN, Age/Sex/Weight, Ward/Bed, Surgeon, Allergy, Date/Time |
| 1. Admission & Monitoring | NPO, vitals frequency, Foley catheter, UO target calculator, I&O chart |
| 2. NGT Decompression | Size, suction type, output charting, mL-for-mL replacement formula |
| 3. IV Fluid Resuscitation | Bolus phase (NS/LR, targets) + maintenance table with fluid choices & rates |
| 4. Electrolyte Correction | K⁺, Cl⁻, Mg²⁺, Na⁺ — deficit, dose, rate, max infusion rules + RED warning box |
| 5. Investigations | Two-column checklist (bloods + imaging) with clinical notes |
| 6. Medications | Analgesia, antiemetics, PPI, DVT prophylaxis, antibiotic guide by severity |
| 7. Monitoring Targets | Table with parameter → target → frequency → action if not met |
| 8. Surgical Escalation | Red-highlighted 8-point escalation criteria checklist |
| 9. Quick Reference | Fluid selection guide by clinical scenario |
| 10. Signatures | Ordering physician, designation, countersign fields |