Ali2206 commited on
Commit
91ded52
·
verified ·
1 Parent(s): 5b460da

Update api/routes/pdf.py

Browse files
Files changed (1) hide show
  1. api/routes/pdf.py +99 -73
api/routes/pdf.py CHANGED
@@ -40,70 +40,75 @@ async def generate_patient_pdf(patient_id: str, current_user: dict = Depends(get
40
  if not patient:
41
  raise HTTPException(status_code=404, detail="Patient not found")
42
 
43
- # Prepare table content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  notes = patient.get("notes", [])
45
- notes_content = ""
46
- if notes:
47
- notes_content = "\\toprule\n" + " \\\\\n".join(
48
- "{} & {} & {}".format(
49
- escape_latex_special_chars(hyphenate_long_strings(format_timestamp(n.get("date", "") or ""))),
50
- escape_latex_special_chars(hyphenate_long_strings(n.get("type", "") or "")),
51
- escape_latex_special_chars(hyphenate_long_strings(n.get("text", "") or ""))
52
- )
53
- for n in notes
54
- ) + "\n\\bottomrule"
55
- else:
56
- notes_content = "\\multicolumn{3}{l}{No notes available}"
57
 
 
58
  conditions = patient.get("conditions", [])
59
- conditions_content = ""
60
- if conditions:
61
- conditions_content = "\\toprule\n" + " \\\\\n".join(
62
- "{} & {} & {} & {} & {}".format(
63
- escape_latex_special_chars(hyphenate_long_strings(c.get("id", "") or "")),
64
- escape_latex_special_chars(hyphenate_long_strings(c.get("code", "") or "")),
65
- escape_latex_special_chars(hyphenate_long_strings(c.get("status", "") or "")),
66
- escape_latex_special_chars(hyphenate_long_strings(format_timestamp(c.get("onset_date", "") or ""))),
67
- escape_latex_special_chars(hyphenate_long_strings(c.get("verification_status", "") or ""))
68
- )
69
- for c in conditions
70
- ) + "\n\\bottomrule"
71
- else:
72
- conditions_content = "\\multicolumn{5}{l}{No conditions available}"
73
 
 
74
  medications = patient.get("medications", [])
75
- medications_content = ""
76
- if medications:
77
- medications_content = "\\toprule\n" + " \\\\\n".join(
78
- "{} & {} & {} & {} & {}".format(
79
- escape_latex_special_chars(hyphenate_long_strings(m.get("id", "") or "")),
80
- escape_latex_special_chars(hyphenate_long_strings(m.get("name", "") or "")),
81
- escape_latex_special_chars(hyphenate_long_strings(m.get("status", "") or "")),
82
- escape_latex_special_chars(hyphenate_long_strings(format_timestamp(m.get("prescribed_date", "") or ""))),
83
- escape_latex_special_chars(hyphenate_long_strings(m.get("dosage", "") or ""))
84
- )
85
- for m in medications
86
- ) + "\n\\bottomrule"
87
- else:
88
- medications_content = "\\multicolumn{5}{l}{No medications available}"
89
 
 
90
  encounters = patient.get("encounters", [])
91
- encounters_content = ""
92
- if encounters:
93
- encounters_content = "\\toprule\n" + " \\\\\n".join(
94
- "{} & {} & {} & {} & {}".format(
95
- escape_latex_special_chars(hyphenate_long_strings(e.get("id", "") or "")),
96
- escape_latex_special_chars(hyphenate_long_strings(e.get("type", "") or "")),
97
- escape_latex_special_chars(hyphenate_long_strings(e.get("status", "") or "")),
98
- escape_latex_special_chars(hyphenate_long_strings(format_timestamp(e.get("period", {}).get("start", "") or ""))),
99
- escape_latex_special_chars(hyphenate_long_strings(e.get("service_provider", "") or ""))
100
- )
101
- for e in encounters
102
- ) + "\n\\bottomrule"
103
- else:
104
- encounters_content = "\\multicolumn{5}{l}{No encounters available}"
105
 
106
- # Use Template for safe insertion
107
  latex_template = Template(r"""
108
  \documentclass[a4paper,12pt]{article}
109
  \usepackage[utf8]{inputenc}
@@ -113,8 +118,8 @@ async def generate_patient_pdf(patient_id: str, current_user: dict = Depends(get
113
  \usepackage{booktabs,longtable,fancyhdr}
114
  \usepackage{array}
115
  \usepackage{microtype}
116
- \microtypesetup{expansion=false} % Disable font expansion to avoid errors
117
- \setlength{\headheight}{14.5pt} % Fix fancyhdr warning
118
  \pagestyle{fancy}
119
  \fancyhf{}
120
  \fancyhead[L]{Patient Report}
@@ -142,31 +147,43 @@ async def generate_patient_pdf(patient_id: str, current_user: dict = Depends(get
142
  \end{itemize}
143
 
144
  \section*{Clinical Notes}
145
- \begin{longtable}{>{\raggedright\arraybackslash}p{3.5cm}>{\raggedright\arraybackslash}p{3cm}>{\raggedright\arraybackslash}p{6.5cm}}
 
 
146
  \textbf{Date} & \textbf{Type} & \textbf{Text} \\
147
- \endhead
148
  $notes
 
149
  \end{longtable}
150
 
151
  \section*{Conditions}
152
- \begin{longtable}{>{\raggedright\arraybackslash}p{2cm}>{\raggedright\arraybackslash}p{3cm}>{\raggedright\arraybackslash}p{2cm}>{\raggedright\arraybackslash}p{3.5cm}>{\raggedright\arraybackslash}p{3cm}}
 
 
153
  \textbf{ID} & \textbf{Code} & \textbf{Status} & \textbf{Onset} & \textbf{Verification} \\
154
- \endhead
155
  $conditions
 
156
  \end{longtable}
157
 
158
  \section*{Medications}
159
- \begin{longtable}{>{\raggedright\arraybackslash}p{2cm}>{\raggedright\arraybackslash}p{4cm}>{\raggedright\arraybackslash}p{2cm}>{\raggedright\arraybackslash}p{3.5cm}>{\raggedright\arraybackslash}p{3cm}}
 
 
160
  \textbf{ID} & \textbf{Name} & \textbf{Status} & \textbf{Date} & \textbf{Dosage} \\
161
- \endhead
162
  $medications
 
163
  \end{longtable}
164
 
165
  \section*{Encounters}
166
- \begin{longtable}{>{\raggedright\arraybackslash}p{2.5cm}>{\raggedright\arraybackslash}p{4.5cm}>{\raggedright\arraybackslash}p{2.5cm}>{\raggedright\arraybackslash}p{4.5cm}>{\raggedright\arraybackslash}p{3.5cm}}
 
 
167
  \textbf{ID} & \textbf{Type} & \textbf{Status} & \textbf{Start} & \textbf{Provider} \\
168
- \endhead
169
  $encounters
 
170
  \end{longtable}
171
 
172
  \end{document}
@@ -206,13 +223,22 @@ $encounters
206
  f.write(latex_filled)
207
 
208
  try:
209
- subprocess.run(
210
- ["latexmk", "-pdf", "-interaction=nonstopmode", tex_path],
211
- cwd=tmpdir,
212
- check=True,
213
- capture_output=True,
214
- text=True
215
- )
 
 
 
 
 
 
 
 
 
216
  except subprocess.CalledProcessError as e:
217
  raise HTTPException(
218
  status_code=500,
 
40
  if not patient:
41
  raise HTTPException(status_code=404, detail="Patient not found")
42
 
43
+ # Prepare table content with proper LaTeX formatting
44
+ def prepare_table_content(items, columns, default_message):
45
+ if not items:
46
+ return f"\\multicolumn{{{columns}}}{{l}}{{{default_message}}} \\\\"
47
+
48
+ content = []
49
+ for item in items:
50
+ row = []
51
+ for field in item:
52
+ value = item.get(field, "") or ""
53
+ row.append(escape_latex_special_chars(hyphenate_long_strings(value)))
54
+ content.append(" & ".join(row) + " \\\\")
55
+ return "\n".join(content)
56
+
57
+ # Notes table
58
  notes = patient.get("notes", [])
59
+ notes_content = prepare_table_content(
60
+ [{
61
+ "date": format_timestamp(n.get("date", "")),
62
+ "type": n.get("type", ""),
63
+ "text": n.get("text", "")
64
+ } for n in notes],
65
+ 3,
66
+ "No notes available"
67
+ )
 
 
 
68
 
69
+ # Conditions table
70
  conditions = patient.get("conditions", [])
71
+ conditions_content = prepare_table_content(
72
+ [{
73
+ "id": c.get("id", ""),
74
+ "code": c.get("code", ""),
75
+ "status": c.get("status", ""),
76
+ "onset": format_timestamp(c.get("onset_date", "")),
77
+ "verification": c.get("verification_status", "")
78
+ } for c in conditions],
79
+ 5,
80
+ "No conditions available"
81
+ )
 
 
 
82
 
83
+ # Medications table
84
  medications = patient.get("medications", [])
85
+ medications_content = prepare_table_content(
86
+ [{
87
+ "id": m.get("id", ""),
88
+ "name": m.get("name", ""),
89
+ "status": m.get("status", ""),
90
+ "date": format_timestamp(m.get("prescribed_date", "")),
91
+ "dosage": m.get("dosage", "")
92
+ } for m in medications],
93
+ 5,
94
+ "No medications available"
95
+ )
 
 
 
96
 
97
+ # Encounters table
98
  encounters = patient.get("encounters", [])
99
+ encounters_content = prepare_table_content(
100
+ [{
101
+ "id": e.get("id", ""),
102
+ "type": e.get("type", ""),
103
+ "status": e.get("status", ""),
104
+ "start": format_timestamp(e.get("period", {}).get("start", "")),
105
+ "provider": e.get("service_provider", "")
106
+ } for e in encounters],
107
+ 5,
108
+ "No encounters available"
109
+ )
 
 
 
110
 
111
+ # LaTeX template with improved table formatting
112
  latex_template = Template(r"""
113
  \documentclass[a4paper,12pt]{article}
114
  \usepackage[utf8]{inputenc}
 
118
  \usepackage{booktabs,longtable,fancyhdr}
119
  \usepackage{array}
120
  \usepackage{microtype}
121
+ \microtypesetup{expansion=false}
122
+ \setlength{\headheight}{14.5pt}
123
  \pagestyle{fancy}
124
  \fancyhf{}
125
  \fancyhead[L]{Patient Report}
 
147
  \end{itemize}
148
 
149
  \section*{Clinical Notes}
150
+ \begin{longtable}[l]{>{\raggedright\arraybackslash}p{3.5cm}>{\raggedright\arraybackslash}p{3cm}>{\raggedright\arraybackslash}p{6.5cm}}
151
+ \caption{Clinical Notes} \\
152
+ \toprule
153
  \textbf{Date} & \textbf{Type} & \textbf{Text} \\
154
+ \midrule
155
  $notes
156
+ \bottomrule
157
  \end{longtable}
158
 
159
  \section*{Conditions}
160
+ \begin{longtable}[l]{>{\raggedright\arraybackslash}p{2cm}>{\raggedright\arraybackslash}p{3cm}>{\raggedright\arraybackslash}p{2cm}>{\raggedright\arraybackslash}p{3.5cm}>{\raggedright\arraybackslash}p{3cm}}
161
+ \caption{Conditions} \\
162
+ \toprule
163
  \textbf{ID} & \textbf{Code} & \textbf{Status} & \textbf{Onset} & \textbf{Verification} \\
164
+ \midrule
165
  $conditions
166
+ \bottomrule
167
  \end{longtable}
168
 
169
  \section*{Medications}
170
+ \begin{longtable}[l]{>{\raggedright\arraybackslash}p{2cm}>{\raggedright\arraybackslash}p{4cm}>{\raggedright\arraybackslash}p{2cm}>{\raggedright\arraybackslash}p{3.5cm}>{\raggedright\arraybackslash}p{3cm}}
171
+ \caption{Medications} \\
172
+ \toprule
173
  \textbf{ID} & \textbf{Name} & \textbf{Status} & \textbf{Date} & \textbf{Dosage} \\
174
+ \midrule
175
  $medications
176
+ \bottomrule
177
  \end{longtable}
178
 
179
  \section*{Encounters}
180
+ \begin{longtable}[l]{>{\raggedright\arraybackslash}p{2.5cm}>{\raggedright\arraybackslash}p{4.5cm}>{\raggedright\arraybackslash}p{2.5cm}>{\raggedright\arraybackslash}p{4.5cm}>{\raggedright\arraybackslash}p{3.5cm}}
181
+ \caption{Encounters} \\
182
+ \toprule
183
  \textbf{ID} & \textbf{Type} & \textbf{Status} & \textbf{Start} & \textbf{Provider} \\
184
+ \midrule
185
  $encounters
186
+ \bottomrule
187
  \end{longtable}
188
 
189
  \end{document}
 
223
  f.write(latex_filled)
224
 
225
  try:
226
+ # Run latexmk twice to ensure proper table rendering
227
+ for _ in range(2):
228
+ result = subprocess.run(
229
+ ["latexmk", "-pdf", "-interaction=nonstopmode", tex_path],
230
+ cwd=tmpdir,
231
+ check=False,
232
+ capture_output=True,
233
+ text=True
234
+ )
235
+
236
+ if result.returncode != 0:
237
+ raise HTTPException(
238
+ status_code=500,
239
+ detail=f"LaTeX compilation failed: stdout={result.stdout}, stderr={result.stderr}"
240
+ )
241
+
242
  except subprocess.CalledProcessError as e:
243
  raise HTTPException(
244
  status_code=500,