Make discharge summary format for medical oncology with USG abdomen, biopsy, ct scans, pet ct, and lab investigations, with discharge medication no pdf
ls /home/daytona/workspace/ 2>/dev/null && ls /home/daytona/skills/docx/scripts/…
mkdir -p /home/daytona/workspace/oncology-discharge && ls /home/daytona/workspac…
~/oncology-discharge/generate.js
const {
Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
AlignmentType, HeadingLevel, BorderStyle, WidthType, VerticalAlign,
ShadingType, LevelFormat, Header, Footer, PageNumber,
NumberFormat, UnderlineType
} = require('docx');
const fs = require('fs');
// ─── Colour palette ──────────────────────────────────────────────────────────
const DARK_BLUE = "1A3C6E";
const MID_BLUE = "2E6DA4";
const LIGHT_BLUE = "D6E4F0";
const HEADER_BG = "1A3C6E";
const ALT_ROW = "EBF3FB";
const WHITE = "FFFFFF";
const BORDER_CLR = "2E6DA4";
// ─── Helpers ─────────────────────────────────────────────────────────────────
const noBorder = { style: BorderStyle.NONE, size: 0, color: "FFFFFF" };
const thinBorder = { style: BorderStyle.SINGLE, size: 6, color: BORDER_CLR };
const thickBorder = { style: BorderStyle.SINGLE, size: 12, color: DARK_BLUE };
function sectionHeading(text) {
return new Paragraph({
spacing: { before: 220, after: 60 },
border: { bottom: { style: BorderStyle.SINGLE, size: 10, color: MID_BLUE } },
children: [
new TextRun({
text,
bold: true,
size: 24,
color: DARK_BLUE,
font: "Arial",
allCaps: true,
}),
],
});
}
function subHeading(text) {
return new Paragraph({
spacing: { before: 120, after: 40 },
children: [
new TextRun({
text,
bold: true,
size: 22,
color: MID_BLUE,
font: "Arial",
}),
],
});
}
function labelValue(label, value = "_______________________________") {
return new Paragraph({
spacing: { before: 40, after: 40 },
children: [
new TextRun({ text: label + ": ", bold: true, size: 20, font: "Arial", color: "333333" }),
new TextRun({ text: value, size: 20, font: "Arial", color: "555555" }),
],
});
}
function plainText(text, opts = {}) {
return new Paragraph({
spacing: { before: 30, after: 30 },
children: [
new TextRun({
text,
size: opts.size || 20,
font: "Arial",
color: opts.color || "444444",
bold: opts.bold || false,
italics: opts.italics || false,
}),
],
});
}
function emptyLine() {
return new Paragraph({ spacing: { before: 40, after: 40 }, children: [new TextRun("")] });
}
// ─── Header row for tables ────────────────────────────────────────────────────
function theadCell(text, widthPct) {
return new TableCell({
width: { size: widthPct, type: WidthType.PERCENTAGE },
shading: { fill: HEADER_BG, type: ShadingType.CLEAR, color: "auto" },
borders: { top: thinBorder, bottom: thinBorder, left: thinBorder, right: thinBorder },
verticalAlign: VerticalAlign.CENTER,
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
children: [new TextRun({ text, bold: true, color: WHITE, size: 20, font: "Arial" })],
}),
],
});
}
function tdCell(text, widthPct, shade = false) {
return new TableCell({
width: { size: widthPct, type: WidthType.PERCENTAGE },
shading: shade ? { fill: ALT_ROW, type: ShadingType.CLEAR, color: "auto" } : undefined,
borders: { top: thinBorder, bottom: thinBorder, left: thinBorder, right: thinBorder },
verticalAlign: VerticalAlign.CENTER,
children: [
new Paragraph({
children: [new TextRun({ text, size: 20, font: "Arial", color: "333333" })],
}),
],
});
}
function tdCellBold(text, widthPct, shade = false) {
return new TableCell({
width: { size: widthPct, type: WidthType.PERCENTAGE },
shading: shade ? { fill: ALT_ROW, type: ShadingType.CLEAR, color: "auto" } : undefined,
borders: { top: thinBorder, bottom: thinBorder, left: thinBorder, right: thinBorder },
verticalAlign: VerticalAlign.CENTER,
children: [
new Paragraph({
children: [new TextRun({ text, size: 20, font: "Arial", color: "333333", bold: true })],
}),
],
});
}
// ─── Build document ───────────────────────────────────────────────────────────
const doc = new Document({
numbering: {
config: [
{
reference: "bullets",
levels: [{
level: 0, format: LevelFormat.BULLET, text: "\u2022",
alignment: AlignmentType.LEFT,
style: { paragraph: { indent: { left: 720, hanging: 360 } } }
}]
}
]
},
styles: {
default: {
document: { run: { font: "Arial", size: 20 } }
}
},
sections: [{
properties: {
page: {
margin: { top: 720, bottom: 720, left: 900, right: 900 },
size: { width: 11906, height: 16838 }
}
},
headers: {
default: new Header({
children: [
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
new TableCell({
width: { size: 100, type: WidthType.PERCENTAGE },
shading: { fill: DARK_BLUE, type: ShadingType.CLEAR },
borders: { top: noBorder, bottom: noBorder, left: noBorder, right: noBorder },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 80, after: 20 },
children: [new TextRun({ text: "DEPARTMENT OF MEDICAL ONCOLOGY", bold: true, size: 28, color: WHITE, font: "Arial" })]
}),
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 0, after: 80 },
children: [new TextRun({ text: "DISCHARGE SUMMARY", bold: true, size: 36, color: "F0C040", font: "Arial" })]
}),
]
})
]
})
]
})
]
})
},
footers: {
default: new Footer({
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
border: { top: { style: BorderStyle.SINGLE, size: 6, color: MID_BLUE } },
spacing: { before: 60 },
children: [
new TextRun({ text: "This document is confidential. For medical use only. | Page ", size: 18, font: "Arial", color: "888888" }),
new TextRun({ children: [new PageNumber()], size: 18, font: "Arial", color: MID_BLUE }),
]
})
]
})
},
children: [
// ══════════════════════════════════════════════════════════
// SECTION 1: PATIENT IDENTIFICATION
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("1. Patient Identification"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
tdCellBold("Patient Name:", 25, false),
tdCell("", 25, false),
tdCellBold("MRD / IP No.:", 25, true),
tdCell("", 25, true),
]
}),
new TableRow({
children: [
tdCellBold("Age / Sex:", 25, false),
tdCell("", 25, false),
tdCellBold("Date of Birth:", 25, true),
tdCell("", 25, true),
]
}),
new TableRow({
children: [
tdCellBold("Address:", 25, false),
tdCell("", 25, false),
tdCellBold("Contact No.:", 25, true),
tdCell("", 25, true),
]
}),
new TableRow({
children: [
tdCellBold("Referred By:", 25, false),
tdCell("", 25, false),
tdCellBold("Referring Hospital:", 25, true),
tdCell("", 25, true),
]
}),
new TableRow({
children: [
tdCellBold("Date of Admission:", 25, false),
tdCell("", 25, false),
tdCellBold("Date of Discharge:", 25, true),
tdCell("", 25, true),
]
}),
new TableRow({
children: [
tdCellBold("Ward / Bed No.:", 25, false),
tdCell("", 25, false),
tdCellBold("Length of Stay:", 25, true),
tdCell("", 25, true),
]
}),
new TableRow({
children: [
tdCellBold("Consultant Oncologist:", 25, false),
tdCell("", 25, false),
tdCellBold("Resident / Fellow:", 25, true),
tdCell("", 25, true),
]
}),
]
}),
// ══════════════════════════════════════════════════════════
// SECTION 2: DIAGNOSIS
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("2. Oncological Diagnosis"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
tdCellBold("Primary Diagnosis:", 30, false),
tdCell("", 70, false),
]
}),
new TableRow({
children: [
tdCellBold("Histological Type:", 30, true),
tdCell("", 70, true),
]
}),
new TableRow({
children: [
tdCellBold("Primary Site:", 30, false),
tdCell("", 70, false),
]
}),
new TableRow({
children: [
tdCellBold("Metastatic Sites:", 30, true),
tdCell("", 70, true),
]
}),
new TableRow({
children: [
tdCellBold("TNM Staging:", 30, false),
tdCell("T:_____ N:_____ M:_____", 70, false),
]
}),
new TableRow({
children: [
tdCellBold("Overall Stage:", 30, true),
tdCell("Stage I / II / III / IV (circle)", 70, true),
]
}),
new TableRow({
children: [
tdCellBold("ECOG Performance Status:", 30, false),
tdCell("0 / 1 / 2 / 3 / 4 (circle)", 70, false),
]
}),
new TableRow({
children: [
tdCellBold("IHC / Molecular Markers:", 30, true),
tdCell("ER:___ PR:___ HER2:___ KRAS:___ EGFR:___ ALK:___ PDL1:___ Other:___", 70, true),
]
}),
new TableRow({
children: [
tdCellBold("Reason for Current Admission:", 30, false),
tdCell("", 70, false),
]
}),
]
}),
// ══════════════════════════════════════════════════════════
// SECTION 3: CLINICAL HISTORY
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("3. Clinical History & Examination"),
subHeading("Chief Complaints:"),
plainText("1. _______________________________________________"),
plainText("2. _______________________________________________"),
plainText("3. _______________________________________________"),
emptyLine(),
subHeading("History of Present Illness:"),
plainText("_________________________________________________________________________________"),
plainText("_________________________________________________________________________________"),
plainText("_________________________________________________________________________________"),
emptyLine(),
subHeading("Past Medical / Surgical / Family / Social History:"),
plainText("_________________________________________________________________________________"),
plainText("_________________________________________________________________________________"),
emptyLine(),
subHeading("Vital Signs on Admission:"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("BP (mmHg)", 17),
theadCell("Pulse (bpm)", 17),
theadCell("Temp (°F)", 17),
theadCell("SpO2 (%)", 17),
theadCell("RR (/min)", 16),
theadCell("Weight (kg)", 16),
]
}),
new TableRow({
children: [
tdCell("", 17), tdCell("", 17), tdCell("", 17),
tdCell("", 17), tdCell("", 16), tdCell("", 16),
]
}),
]
}),
// ══════════════════════════════════════════════════════════
// SECTION 4: LABORATORY INVESTIGATIONS
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("4. Laboratory Investigations"),
subHeading("Complete Blood Count (CBC):"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("Parameter", 28),
theadCell("Admission Value", 24),
theadCell("Discharge Value", 24),
theadCell("Reference Range", 24),
]
}),
...[
["Hb (g/dL)", "", "", "12.0 - 17.0"],
["TLC (cells/µL)", "", "", "4000 - 11000"],
["Platelets (lakhs/µL)", "", "", "1.5 - 4.0"],
["Neutrophils (%)", "", "", "50 - 70"],
["Lymphocytes (%)", "", "", "20 - 40"],
["MCV (fL)", "", "", "80 - 100"],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 28, i % 2 !== 0),
tdCell(r[1], 24, i % 2 !== 0),
tdCell(r[2], 24, i % 2 !== 0),
tdCell(r[3], 24, i % 2 !== 0),
]
}))
]
}),
emptyLine(),
subHeading("Biochemistry & Metabolic Panel:"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("Parameter", 28),
theadCell("Admission Value", 24),
theadCell("Discharge Value", 24),
theadCell("Reference Range", 24),
]
}),
...[
["Blood Urea (mg/dL)", "", "", "15 - 40"],
["Serum Creatinine (mg/dL)", "", "", "0.6 - 1.2"],
["eGFR (mL/min)", "", "", "> 60"],
["Serum Sodium (mEq/L)", "", "", "135 - 145"],
["Serum Potassium (mEq/L)", "", "", "3.5 - 5.0"],
["Serum Calcium (mg/dL)", "", "", "8.5 - 10.5"],
["Serum Albumin (g/dL)", "", "", "3.5 - 5.0"],
["Total Bilirubin (mg/dL)", "", "", "0.2 - 1.2"],
["Direct Bilirubin (mg/dL)", "", "", "0.0 - 0.4"],
["AST / SGOT (U/L)", "", "", "< 40"],
["ALT / SGPT (U/L)", "", "", "< 40"],
["ALP (U/L)", "", "", "40 - 130"],
["GGT (U/L)", "", "", "< 55"],
["LDH (U/L)", "", "", "140 - 280"],
["Blood Glucose - Fasting (mg/dL)", "", "", "70 - 100"],
["HbA1c (%)", "", "", "< 5.7"],
["PT / INR", "", "", "0.8 - 1.2"],
["aPTT (sec)", "", "", "25 - 35"],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 28, i % 2 !== 0),
tdCell(r[1], 24, i % 2 !== 0),
tdCell(r[2], 24, i % 2 !== 0),
tdCell(r[3], 24, i % 2 !== 0),
]
}))
]
}),
emptyLine(),
subHeading("Tumour Markers:"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("Marker", 28),
theadCell("Pre-treatment Value", 24),
theadCell("Post-treatment Value", 24),
theadCell("Reference Range", 24),
]
}),
...[
["CEA (ng/mL)", "", "", "< 2.5 (non-smoker)"],
["CA 19-9 (U/mL)", "", "", "< 37"],
["CA 125 (U/mL)", "", "", "< 35"],
["CA 15-3 (U/mL)", "", "", "< 30"],
["PSA - Total (ng/mL)", "", "", "< 4.0"],
["AFP (ng/mL)", "", "", "< 7.0"],
["Beta-hCG (mIU/mL)", "", "", "< 5"],
["LDH (U/L)", "", "", "140 - 280"],
["Beta-2 Microglobulin", "", "", "< 3.0 mg/L"],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 28, i % 2 !== 0),
tdCell(r[1], 24, i % 2 !== 0),
tdCell(r[2], 24, i % 2 !== 0),
tdCell(r[3], 24, i % 2 !== 0),
]
}))
]
}),
emptyLine(),
subHeading("Other Relevant Investigations:"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("Investigation", 35),
theadCell("Result / Finding", 40),
theadCell("Date", 25),
]
}),
...[
["Thyroid Function (TSH / T3 / T4)", "", ""],
["Urine Routine & Microscopy", "", ""],
["Urine 24hr Protein", "", ""],
["Serum Protein Electrophoresis (SPEP)", "", ""],
["Bone Marrow Biopsy (if done)", "", ""],
["Flow Cytometry / Immunophenotyping", "", ""],
["Cytogenetics / FISH", "", ""],
["Next Generation Sequencing (NGS)", "", ""],
["BRCA 1 / BRCA 2 Mutation Status", "", ""],
["Other:", "", ""],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 35, i % 2 !== 0),
tdCell(r[1], 40, i % 2 !== 0),
tdCell(r[2], 25, i % 2 !== 0),
]
}))
]
}),
// ══════════════════════════════════════════════════════════
// SECTION 5: BIOPSY
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("5. Biopsy / Histopathology Report"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("Parameter", 30),
theadCell("Details", 70),
]
}),
...[
["Biopsy Site / Specimen:", ""],
["Type of Biopsy:", "FNAC / Core Needle / Excision / Tru-cut / Punch / Endoscopic"],
["Date of Biopsy:", ""],
["Pathology Report No.:", ""],
["Macroscopy:", ""],
["Microscopy / Histology:", ""],
["Diagnosis / Impression:", ""],
["Grade (WHO / Bloom-Richardson):", ""],
["Lymphovascular Invasion (LVI):", "Present / Absent"],
["Perineural Invasion (PNI):", "Present / Absent"],
["Surgical Margins (if applicable):", "Clear / Involved / Not applicable"],
["Ki-67 / Proliferative Index:", ""],
["IHC Panel - ER:", "Positive (____%) / Negative"],
["IHC Panel - PR:", "Positive (____%) / Negative"],
["IHC Panel - HER2:", "0 / 1+ / 2+ / 3+ (FISH if 2+: ______)"],
["IHC Panel - KRAS / NRAS:", "Wild-type / Mutated (Codon:___)"],
["IHC Panel - EGFR:", "Wild-type / Mutated (Exon:___)"],
["IHC Panel - ALK:", "Positive / Negative"],
["IHC Panel - PDL1 (TPS/CPS):", "TPS:____% CPS:____"],
["IHC Panel - CD20 / CD3 / Others:", ""],
["Additional IHC / Special Stains:", ""],
["Reporting Pathologist:", ""],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 30, i % 2 !== 0),
tdCell(r[1], 70, i % 2 !== 0),
]
}))
]
}),
// ══════════════════════════════════════════════════════════
// SECTION 6: USG ABDOMEN
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("6. Ultrasonography (USG) Abdomen & Pelvis"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("Parameter", 30),
theadCell("Findings", 70),
]
}),
...[
["Date of USG:", ""],
["Type:", "USG Abdomen / USG Abdomen + Pelvis / Whole Abdomen"],
["Radiologist:", ""],
["Liver:", "Size:_______ Echotexture:_______ Focal Lesions:_______"],
["Number / Size of Liver Lesions:", ""],
["Gall Bladder & Biliary System:", ""],
["Spleen:", "Size:_______ cm Echo:_______"],
["Pancreas:", ""],
["Kidneys (Right / Left):", "Size (R):_______ (L):_______ Hydroureteronephrosis:_______"],
["Urinary Bladder:", ""],
["Aorta / IVC:", ""],
["Lymph Nodes (Para-aortic / Iliac):", ""],
["Ascites:", "Absent / Present (Mild / Moderate / Gross)"],
["Pleural Effusion (if visible):", "Absent / Present (Right / Left / Bilateral)"],
["Uterus / Adnexa (Female):", ""],
["Prostate (Male):", ""],
["Primary Lesion (if visible):", "Site:_______ Size:_______ Characteristics:_______"],
["Other Findings:", ""],
["Impression:", ""],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 30, i % 2 !== 0),
tdCell(r[1], 70, i % 2 !== 0),
]
}))
]
}),
// ══════════════════════════════════════════════════════════
// SECTION 7: CT SCANS
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("7. Computed Tomography (CT) Scan Reports"),
subHeading("CT Chest / Thorax:"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [theadCell("Parameter", 30), theadCell("Findings", 70)]
}),
...[
["Date:", ""],
["Type:", "Plain / Contrast / HRCT / CT Angiography"],
["Radiologist:", ""],
["Lungs:", ""],
["Primary Lung Lesion (if any):", "Lobe:_______ Size:_______ Characteristics:_______"],
["Pulmonary Nodules:", "Number:_______ Max Size:_______"],
["Pleural Effusion:", "Absent / Present (R / L / Bilateral)"],
["Mediastinum:", ""],
["Mediastinal Lymph Nodes:", "Station:_______ Size:_______"],
["Pericardium:", ""],
["Great Vessels:", ""],
["Chest Wall Involvement:", ""],
["Bone Involvement (Ribs / Sternum / Spine):", ""],
["Impression:", ""],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 30, i % 2 !== 0),
tdCell(r[1], 70, i % 2 !== 0),
]
}))
]
}),
emptyLine(),
subHeading("CT Abdomen & Pelvis:"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [theadCell("Parameter", 30), theadCell("Findings", 70)]
}),
...[
["Date:", ""],
["Type:", "Plain / Triphasic / Contrast / CT Enterography"],
["Radiologist:", ""],
["Liver (segments):", "Number:_______ Size:_______ Enhancement:_______"],
["Gall Bladder / Bile Ducts:", ""],
["Pancreas:", ""],
["Spleen:", "Size:_______ Lesions:_______"],
["Stomach / Bowel:", ""],
["Primary Tumor (site & size):", ""],
["Peritoneum / Omentum:", "Carcinomatosis: Absent / Present"],
["Adrenal Glands:", ""],
["Kidneys & Ureters:", ""],
["Retroperitoneal LN:", ""],
["Pelvic Organs / LN:", ""],
["Ascites:", "Absent / Mild / Moderate / Gross"],
["Bone (visible vertebrae / pelvis):", ""],
["Impression:", ""],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 30, i % 2 !== 0),
tdCell(r[1], 70, i % 2 !== 0),
]
}))
]
}),
emptyLine(),
subHeading("CT Brain (if performed):"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [theadCell("Parameter", 30), theadCell("Findings", 70)]
}),
...[
["Date:", ""],
["Type:", "Plain / Contrast / CT Angiography"],
["Radiologist:", ""],
["Parenchyma:", ""],
["Metastatic Lesions:", "Number:_______ Max Size:_______ Sites:_______"],
["Oedema / Mass Effect:", ""],
["Midline Shift:", "Absent / Present (____mm)"],
["Meningeal Enhancement:", "Absent / Present"],
["Calvarium / Skull Base:", ""],
["Impression:", ""],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 30, i % 2 !== 0),
tdCell(r[1], 70, i % 2 !== 0),
]
}))
]
}),
// ══════════════════════════════════════════════════════════
// SECTION 8: PET-CT
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("8. PET-CT Scan Report (FDG / PSMA / DOTANOC)"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [theadCell("Parameter", 30), theadCell("Findings", 70)]
}),
...[
["Date of PET-CT:", ""],
["Type of Tracer:", "18F-FDG / 68Ga-PSMA / 68Ga-DOTANOC / 18F-NaF / Other:_____"],
["Purpose:", "Staging / Restaging / Treatment Response / Recurrence workup"],
["Serum Blood Glucose (pre-scan):", ""],
["Radiologist / Nuclear Medicine Physician:", ""],
["Primary Tumor Site:", "Site:_______ SUVmax:_______ Size:_______"],
["Regional Lymph Nodes:", "Sites:_______ SUVmax:_______"],
["Distant Metastases - Liver:", "Number:_______ SUVmax:_______"],
["Distant Metastases - Lung:", "Number:_______ SUVmax:_______"],
["Distant Metastases - Bone:", "Sites:_______ SUVmax:_______ Sclerotic / Lytic"],
["Distant Metastases - Brain:", "Number:_______ SUVmax:_______"],
["Distant Metastases - Adrenal:", "R/L:_______ SUVmax:_______"],
["Distant Metastases - Other:", "Site:_______ SUVmax:_______"],
["Peritoneal / Omental Deposits:", "Absent / Present"],
["Pleural Involvement:", "Absent / Present"],
["Total Metabolic Tumor Volume (TMTV):", ""],
["Total Lesion Glycolysis (TLG):", ""],
["Deauville Score (lymphoma):", "1 / 2 / 3 / 4 / 5 (if applicable)"],
["PERCIST / RECIST Response Category:", "CR / PR / SD / PD (if response scan)"],
["Impression / Conclusion:", ""],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 30, i % 2 !== 0),
tdCell(r[1], 70, i % 2 !== 0),
]
}))
]
}),
// ══════════════════════════════════════════════════════════
// SECTION 9: TREATMENT GIVEN
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("9. Treatment Given During This Admission"),
subHeading("Chemotherapy / Targeted Therapy / Immunotherapy Administered:"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("Drug Name", 28),
theadCell("Dose", 15),
theadCell("Route", 12),
theadCell("Day(s) Given", 20),
theadCell("Cycle No.", 13),
theadCell("Remarks", 12),
]
}),
...[1,2,3,4,5].map((n, i) => new TableRow({
children: [
tdCell("", 28, i % 2 !== 0),
tdCell("", 15, i % 2 !== 0),
tdCell("", 12, i % 2 !== 0),
tdCell("", 20, i % 2 !== 0),
tdCell("", 13, i % 2 !== 0),
tdCell("", 12, i % 2 !== 0),
]
}))
]
}),
emptyLine(),
subHeading("Regimen Name / Protocol:"),
plainText("_________________________________________________________________________________"),
emptyLine(),
subHeading("Pre-medications & Supportive Therapy Given:"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("Drug / Intervention", 40),
theadCell("Dose & Frequency", 30),
theadCell("Remarks", 30),
]
}),
...[
["Anti-emetics (Ondansetron / Granisetron)", "", ""],
["Corticosteroids (Dexamethasone)", "", ""],
["Antihistamines (Diphenhydramine)", "", ""],
["G-CSF / PEG-GCSF (Filgrastim)", "", ""],
["Hydration (IV Fluids)", "", ""],
["Urine alkalinization / Mesna", "", ""],
["Allopurinol / Rasburicase (TLS prophylaxis)", "", ""],
["Blood / Platelet Transfusion", "", ""],
["Antibiotics (specify)", "", ""],
["Analgesics / Pain management", "", ""],
["Other:", "", ""],
].map((r, i) => new TableRow({
children: [
tdCellBold(r[0], 40, i % 2 !== 0),
tdCell(r[1], 30, i % 2 !== 0),
tdCell(r[2], 30, i % 2 !== 0),
]
}))
]
}),
emptyLine(),
subHeading("Complications / Adverse Events During Admission:"),
plainText("Toxicity Grade (CTCAE v5.0): _______________________________________________"),
plainText("Adverse Event Description: _________________________________________________"),
plainText("Management: ________________________________________________________________"),
// ══════════════════════════════════════════════════════════
// SECTION 10: DISCHARGE MEDICATIONS
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("10. Discharge Medications"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
theadCell("S.No.", 5),
theadCell("Drug Name (Generic / Brand)", 28),
theadCell("Dose", 12),
theadCell("Route", 9),
theadCell("Frequency", 13),
theadCell("Duration", 12),
theadCell("Instructions", 21),
]
}),
...[1,2,3,4,5,6,7,8,9,10,11,12].map((n, i) => new TableRow({
children: [
tdCellBold(`${n}.`, 5, i % 2 !== 0),
tdCell("", 28, i % 2 !== 0),
tdCell("", 12, i % 2 !== 0),
tdCell("", 9, i % 2 !== 0),
tdCell("", 13, i % 2 !== 0),
tdCell("", 12, i % 2 !== 0),
tdCell("", 21, i % 2 !== 0),
]
}))
]
}),
emptyLine(),
subHeading("Special Medication Instructions:"),
plainText("Oral Chemotherapy / Targeted Agents: __________________________________________"),
plainText("Steroids tapering schedule: ___________________________________________________"),
plainText("Anticoagulation (LMWH / Warfarin / DOAC): ____________________________________"),
plainText("Hormonal Therapy: _____________________________________________________________"),
plainText("Bisphosphonates / Denosumab: _________________________________________________"),
plainText("Growth Factors: _______________________________________________________________"),
// ══════════════════════════════════════════════════════════
// SECTION 11: CONDITION AT DISCHARGE
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("11. Condition at Discharge"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
tdCellBold("Discharge Condition:", 25, false),
tdCell("Stable / Improved / Against Medical Advice / LAMA", 75, false),
]
}),
new TableRow({
children: [
tdCellBold("ECOG PS at Discharge:", 25, true),
tdCell("0 / 1 / 2 / 3 / 4", 75, true),
]
}),
new TableRow({
children: [
tdCellBold("Vital Signs at Discharge:", 25, false),
tdCell("BP:_____ Pulse:_____ Temp:_____ SpO2:_____ Weight:_____", 75, false),
]
}),
new TableRow({
children: [
tdCellBold("Treatment Response:", 25, true),
tdCell("CR / PR / SD / PD / Not evaluable / First treatment (N/A)", 75, true),
]
}),
new TableRow({
children: [
tdCellBold("Next Planned Intervention:", 25, false),
tdCell("Cycle:_____ Drug:_____ Date:_____ Modality:_____", 75, false),
]
}),
]
}),
// ══════════════════════════════════════════════════════════
// SECTION 12: FOLLOW-UP & ADVICE
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("12. Follow-up & Discharge Advice"),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
tdCellBold("Follow-up Date:", 25, false),
tdCell("", 75, false),
]
}),
new TableRow({
children: [
tdCellBold("Follow-up With:", 25, true),
tdCell("Oncologist / Radiation Oncologist / Surgeon / MDT", 75, true),
]
}),
new TableRow({
children: [
tdCellBold("Investigations to Repeat:", 25, false),
tdCell("CBC / LFT / RFT / Tumour Markers / Imaging (specify:____)", 75, false),
]
}),
new TableRow({
children: [
tdCellBold("Diet Instructions:", 25, true),
tdCell("", 75, true),
]
}),
new TableRow({
children: [
tdCellBold("Activity Restriction:", 25, false),
tdCell("", 75, false),
]
}),
new TableRow({
children: [
tdCellBold("Wound / Port Care:", 25, true),
tdCell("", 75, true),
]
}),
new TableRow({
children: [
tdCellBold("Emergency Contact:", 25, false),
tdCell("Report immediately if: fever > 38°C, bleeding, severe vomiting, breathlessness", 75, false),
]
}),
]
}),
emptyLine(),
subHeading("Patient / Attendant Education Given:"),
plainText("Neutropenic precautions: Yes / No Oral mucositis care: Yes / No"),
plainText("Chemotherapy side-effect counselling: Yes / No Palliative care referral: Yes / No"),
// ══════════════════════════════════════════════════════════
// SECTION 13: SIGNATURES
// ══════════════════════════════════════════════════════════
emptyLine(),
sectionHeading("13. Signatures & Certification"),
emptyLine(),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
new TableCell({
width: { size: 50, type: WidthType.PERCENTAGE },
borders: { top: noBorder, bottom: noBorder, left: noBorder, right: noBorder },
children: [
plainText("Treating Consultant Oncologist"),
emptyLine(),
emptyLine(),
plainText("Signature: ___________________________"),
plainText("Name: _______________________________"),
plainText("Designation: ________________________"),
plainText("Registration No.: ____________________"),
plainText("Date: _______________________________"),
]
}),
new TableCell({
width: { size: 50, type: WidthType.PERCENTAGE },
borders: { top: noBorder, bottom: noBorder, left: noBorder, right: noBorder },
children: [
plainText("Resident / Medical Officer"),
emptyLine(),
emptyLine(),
plainText("Signature: ___________________________"),
plainText("Name: _______________________________"),
plainText("Designation: ________________________"),
plainText("Registration No.: ____________________"),
plainText("Date: _______________________________"),
]
}),
]
})
]
}),
emptyLine(),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
new TableCell({
width: { size: 100, type: WidthType.PERCENTAGE },
shading: { fill: LIGHT_BLUE, type: ShadingType.CLEAR },
borders: { top: thinBorder, bottom: thinBorder, left: thinBorder, right: thinBorder },
children: [
new Paragraph({
alignment: AlignmentType.CENTER,
spacing: { before: 80, after: 40 },
children: [new TextRun({ text: "PATIENT / ATTENDANT ACKNOWLEDGEMENT", bold: true, size: 22, font: "Arial", color: DARK_BLUE })]
}),
plainText("I / We have received and understood the discharge instructions, medications, and follow-up schedule."),
emptyLine(),
new Table({
width: { size: 100, type: WidthType.PERCENTAGE },
rows: [
new TableRow({
children: [
new TableCell({
width: { size: 50, type: WidthType.PERCENTAGE },
borders: { top: noBorder, bottom: noBorder, left: noBorder, right: noBorder },
children: [
plainText("Patient Signature: ___________________"),
plainText("Attendant Name: _____________________"),
plainText("Relation: ___________________________"),
]
}),
new TableCell({
width: { size: 50, type: WidthType.PERCENTAGE },
borders: { top: noBorder, bottom: noBorder, left: noBorder, right: noBorder },
children: [
plainText("Date & Time: _______________________"),
plainText("Contact No.: ________________________"),
]
}),
]
})
]
}),
emptyLine(),
]
})
]
})
]
}),
emptyLine(),
] // end children
}] // end sections
});
Packer.toBuffer(doc).then(buffer => {
fs.writeFileSync('/home/daytona/workspace/oncology-discharge/MedicalOncology_DischargeSummary.docx', buffer);
console.log('Done: MedicalOncology_DischargeSummary.docx created');
});
cd /home/daytona/workspace/oncology-discharge && node generate.js 2>&1
node -e "const d=require('docx'); console.log(Object.keys(d).filter(k=>k.toLower…
node -e "const {PageNumber}=require('docx'); console.log(typeof PageNumber, Obje…
node -e "const {PageNumberElement, SimpleField}=require('docx'); console.log(typ…
~/oncology-discharge/generate.js
Error: String not found in file: ' AlignmentType, HeadingLevel, BorderStyle, WidthType, VerticalAlign, ShadingType, LevelFormat, Header, Footer, PageNumber, NumberFormat, UnderlineType'
~/oncology-discharge/generate.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/oncology-discharge/generate.js'
~/oncology-discharge/generate.js
Successfully replaced 1 instance(s) of the string in '/home/daytona/workspace/oncology-discharge/generate.js'
cd /home/daytona/workspace/oncology-discharge && node generate.js 2>&1
python /home/daytona/skills/docx/scripts/office/validate.py /home/daytona/worksp…
ls -lh /home/daytona/workspace/oncology-discharge/MedicalOncology_DischargeSumma…
MedicalOncology DischargeSummary
Word Document · DOCX
| Section | Contents |
|---|---|
| 1. Patient Identification | Name, MRD/IP No., Age/Sex, DOB, Address, Referral details, Admission/Discharge dates, Ward/Bed, Consultant & Resident names |
| 2. Oncological Diagnosis | Primary diagnosis, histological type, primary site, metastatic sites, TNM staging, overall stage (I-IV), ECOG PS, IHC/molecular markers (ER/PR/HER2/KRAS/EGFR/ALK/PDL1), reason for admission |
| 3. Clinical History & Examination | Chief complaints, HPI, past/family/social history, vital signs table on admission |
| 4. Laboratory Investigations | Full CBC table, biochemistry panel (18 parameters with reference ranges), tumour marker table (CEA, CA 19-9, CA 125, CA 15-3, PSA, AFP, Beta-hCG, LDH, Beta-2M), other investigations (NGS, FISH, SPEP, BRCA etc.) - all with admission vs. discharge values |
| 5. Biopsy / Histopathology | Biopsy site, type (FNAC/core/excision etc.), macro/microscopy, diagnosis, grade, LVI, PNI, margins, Ki-67, full IHC panel, reporting pathologist |
| 6. USG Abdomen & Pelvis | Liver, GB, spleen, pancreas, kidneys, bladder, aorta, lymph nodes, ascites, pleural effusion, uterus/adnexa/prostate, primary lesion |
| 7. CT Scans | Separate sub-sections for CT Chest, CT Abdomen & Pelvis, and CT Brain - each with site-specific fields |
| 8. PET-CT | Tracer type (FDG/PSMA/DOTANOC), SUVmax for primary + all metastatic sites, TMTV, TLG, Deauville score, PERCIST/RECIST response category |
| 9. Treatment Given | Chemo/targeted/immunotherapy drug table (dose/route/cycle), regimen name, pre-medications and supportive care, CTCAE toxicity grading |
| 10. Discharge Medications | 12-row table with drug name, dose, route, frequency, duration, and instructions + special medication notes (oral chemo, steroid taper, anticoagulation, hormonal therapy, bisphosphonates) |
| 11. Condition at Discharge | Discharge condition, ECOG PS, vitals, treatment response (CR/PR/SD/PD), next planned cycle |
| 12. Follow-up & Advice | Follow-up date/with, investigations to repeat, diet, activity, port/wound care, emergency instructions, patient education checklist |
| 13. Signatures | Dual signature block (consultant + resident), patient/attendant acknowledgement with date/time |