Ali2206 commited on
Commit
44fe32c
·
verified ·
1 Parent(s): 2925a8b

Update api/routes/pdf.py

Browse files
Files changed (1) hide show
  1. api/routes/pdf.py +65 -61
api/routes/pdf.py CHANGED
@@ -5,6 +5,7 @@ from utils.helpers import calculate_age, escape_latex_special_chars, hyphenate_l
5
  from datetime import datetime
6
  from bson import ObjectId
7
  from bson.errors import InvalidId
 
8
  import logging
9
  import asyncio
10
  from typing import List, Dict, Optional
@@ -20,109 +21,112 @@ logger = logging.getLogger(__name__)
20
  router = APIRouter()
21
 
22
  # Configuration
23
- SUMMARY_METADATA_COLLECTION = "patient_summary_json"
24
 
25
- async def generate_patient_summary_json(patient: dict) -> Dict:
26
- return {
 
27
  "patient_id": patient.get("fhir_id"),
28
- "patient_name": patient.get("full_name"),
29
- "generated_at": datetime.utcnow(),
30
- "summary": {
31
- "demographics": {
32
- "fhir_id": patient.get("fhir_id"),
33
- "full_name": patient.get("full_name"),
34
- "gender": patient.get("gender"),
35
- "dob": patient.get("date_of_birth"),
36
- "age": calculate_age(patient.get("date_of_birth")),
37
- "address": ", ".join(filter(None, [
38
- patient.get("address", ""),
39
- patient.get("city", ""),
40
- patient.get("state", ""),
41
- patient.get("postal_code", ""),
42
- patient.get("country", "")
43
- ])),
44
- "marital_status": patient.get("marital_status"),
45
- "language": patient.get("language")
46
- },
47
- "notes": patient.get("notes", []),
48
- "conditions": patient.get("conditions", []),
49
- "medications": patient.get("medications", []),
50
- "encounters": patient.get("encounters", [])
51
- }
52
  }
 
53
 
54
  async def generate_and_store_summary(patient: dict) -> Optional[Dict]:
 
55
  try:
56
- summary = await generate_patient_summary_json(patient)
57
  db = patients_collection.database
58
- await db[SUMMARY_METADATA_COLLECTION].update_one(
59
  {"patient_id": summary["patient_id"]},
60
  {"$set": summary},
61
  upsert=True
62
  )
63
- logger.info(f"Stored JSON summary for patient {summary['patient_id']}")
64
  return summary
65
  except Exception as e:
66
- logger.error(f"Error generating/storing summary: {str(e)}")
67
  return None
68
 
69
- async def generate_all_patient_summaries() -> List[Dict]:
70
- generated = []
 
71
  try:
72
- cursor = patients_collection.find({})
73
- patients = await cursor.to_list(length=None)
74
  for patient in patients:
75
  summary = await generate_and_store_summary(patient)
76
  if summary:
77
- generated.append(summary)
78
- return generated
79
  except Exception as e:
80
- logger.error(f"Error generating all summaries: {str(e)}")
81
- return generated
82
 
83
  async def watch_for_new_patients():
 
84
  try:
85
  logger.info("Starting MongoDB change stream for new summaries")
86
- db = patients_collection.database
87
  pipeline = [{'$match': {'operationType': 'insert'}}]
88
  while True:
89
  try:
90
  async with patients_collection.watch(pipeline) as stream:
91
  async for change in stream:
92
- try:
93
- patient = change['fullDocument']
94
- await generate_and_store_summary(patient)
95
- except Exception as e:
96
- logger.error(f"Change stream processing error: {str(e)}")
97
  except PyMongoError as e:
98
- logger.error(f"MongoDB watch error: {str(e)}")
99
  await asyncio.sleep(5)
100
  except Exception as e:
101
- logger.error(f"Fatal error in watcher: {str(e)}")
102
 
103
  @router.on_event("startup")
104
  async def startup_event():
105
  asyncio.create_task(watch_for_new_patients())
 
106
 
107
- @router.post("/generate-all-summaries", status_code=202)
108
- async def trigger_summary_generation(
109
- background_tasks: BackgroundTasks,
110
- current_user: dict = Depends(get_current_user)
111
- ):
112
  if current_user.get('role') not in ['admin', 'doctor']:
113
- raise HTTPException(status_code=403, detail="Only doctors/admins allowed")
114
- background_tasks.add_task(generate_all_patient_summaries)
115
- return {"status": "accepted", "message": "Summary generation started"}
 
 
 
 
116
 
117
- @router.get("/list-summaries", response_model=List[Dict])
118
- async def list_summaries(current_user: dict = Depends(get_current_user)):
 
 
 
 
 
119
  if current_user.get('role') not in ['admin', 'doctor']:
120
- raise HTTPException(status_code=403, detail="Only doctors/admins allowed")
 
121
  try:
122
  db = patients_collection.database
123
- cursor = db[SUMMARY_METADATA_COLLECTION].find({})
124
- return await cursor.to_list(length=None)
125
  except Exception as e:
126
  raise HTTPException(status_code=500, detail=f"Error listing summaries: {str(e)}")
127
 
128
- pdf = router
 
5
  from datetime import datetime
6
  from bson import ObjectId
7
  from bson.errors import InvalidId
8
+ import os
9
  import logging
10
  import asyncio
11
  from typing import List, Dict, Optional
 
21
  router = APIRouter()
22
 
23
  # Configuration
24
+ SUMMARY_COLLECTION = "patient_summary_json"
25
 
26
+ async def generate_summary_json(patient: dict) -> Dict:
27
+ """Generate a structured JSON summary from a patient dict."""
28
+ summary = {
29
  "patient_id": patient.get("fhir_id"),
30
+ "full_name": patient.get("full_name"),
31
+ "gender": patient.get("gender"),
32
+ "date_of_birth": patient.get("date_of_birth"),
33
+ "age": calculate_age(patient.get("date_of_birth")),
34
+ "address": ", ".join(filter(None, [
35
+ patient.get("address"),
36
+ patient.get("city"),
37
+ patient.get("state"),
38
+ patient.get("postal_code"),
39
+ patient.get("country")
40
+ ])),
41
+ "marital_status": patient.get("marital_status"),
42
+ "language": patient.get("language"),
43
+ "notes": patient.get("notes", []),
44
+ "conditions": patient.get("conditions", []),
45
+ "medications": patient.get("medications", []),
46
+ "encounters": patient.get("encounters", []),
47
+ "generated_at": datetime.utcnow()
 
 
 
 
 
 
48
  }
49
+ return summary
50
 
51
  async def generate_and_store_summary(patient: dict) -> Optional[Dict]:
52
+ """Generate and store patient summary JSON in MongoDB."""
53
  try:
54
+ summary = await generate_summary_json(patient)
55
  db = patients_collection.database
56
+ await db[SUMMARY_COLLECTION].update_one(
57
  {"patient_id": summary["patient_id"]},
58
  {"$set": summary},
59
  upsert=True
60
  )
61
+ logger.info(f"Inserted JSON summary for patient {summary['patient_id']}")
62
  return summary
63
  except Exception as e:
64
+ logger.error(f"Error storing summary for patient {patient.get('fhir_id')}: {str(e)}")
65
  return None
66
 
67
+ async def generate_all_summaries() -> List[Dict]:
68
+ """Generate and store summaries for all patients."""
69
+ results = []
70
  try:
71
+ patients = await patients_collection.find({}).to_list(length=None)
 
72
  for patient in patients:
73
  summary = await generate_and_store_summary(patient)
74
  if summary:
75
+ results.append(summary)
76
+ return results
77
  except Exception as e:
78
+ logger.error(f"Error in generate_all_summaries: {str(e)}")
79
+ return results
80
 
81
  async def watch_for_new_patients():
82
+ """Watch MongoDB change stream for new patients and generate summaries."""
83
  try:
84
  logger.info("Starting MongoDB change stream for new summaries")
 
85
  pipeline = [{'$match': {'operationType': 'insert'}}]
86
  while True:
87
  try:
88
  async with patients_collection.watch(pipeline) as stream:
89
  async for change in stream:
90
+ patient = change['fullDocument']
91
+ logger.info(f"New patient detected: {patient.get('fhir_id')}")
92
+ await generate_and_store_summary(patient)
 
 
93
  except PyMongoError as e:
94
+ logger.error(f"MongoDB change stream error: {str(e)}")
95
  await asyncio.sleep(5)
96
  except Exception as e:
97
+ logger.error(f"Fatal error in watch_for_new_patients: {str(e)}")
98
 
99
  @router.on_event("startup")
100
  async def startup_event():
101
  asyncio.create_task(watch_for_new_patients())
102
+ asyncio.create_task(generate_all_summaries())
103
 
104
+ @router.get("/generate-summary/{patient_id}")
105
+ async def generate_summary_for_one(patient_id: str, current_user: dict = Depends(get_current_user)):
 
 
 
106
  if current_user.get('role') not in ['admin', 'doctor']:
107
+ raise HTTPException(status_code=403, detail="Unauthorized")
108
+
109
+ try:
110
+ query = {"fhir_id": patient_id}
111
+ patient = await patients_collection.find_one(query)
112
+ if not patient:
113
+ raise HTTPException(status_code=404, detail="Patient not found")
114
 
115
+ summary = await generate_and_store_summary(patient)
116
+ return {"status": "success", "summary": summary}
117
+ except Exception as e:
118
+ raise HTTPException(status_code=500, detail=str(e))
119
+
120
+ @router.get("/list-json-summaries", response_model=List[Dict])
121
+ async def list_all_summaries(current_user: dict = Depends(get_current_user)):
122
  if current_user.get('role') not in ['admin', 'doctor']:
123
+ raise HTTPException(status_code=403, detail="Unauthorized")
124
+
125
  try:
126
  db = patients_collection.database
127
+ summaries = await db[SUMMARY_COLLECTION].find({}).to_list(length=None)
128
+ return summaries
129
  except Exception as e:
130
  raise HTTPException(status_code=500, detail=f"Error listing summaries: {str(e)}")
131
 
132
+ pdf = router