Ali2206 commited on
Commit
c7fccb3
·
verified ·
1 Parent(s): 2e78e75

Update api/routes/patients.py

Browse files
Files changed (1) hide show
  1. api/routes/patients.py +79 -7
api/routes/patients.py CHANGED
@@ -1,9 +1,9 @@
1
- from fastapi import APIRouter, HTTPException, Depends, Query, status
2
  from db.mongo import patients_collection
3
  from core.security import get_current_user
4
  from utils.db import create_indexes
5
  from utils.helpers import calculate_age, standardize_language
6
- from models.entities import Note
7
  from datetime import datetime
8
  from bson import ObjectId
9
  from bson.errors import InvalidId
@@ -33,6 +33,76 @@ BASE_DIR = Path(__file__).resolve().parent.parent.parent
33
  SYNTHEA_DATA_DIR = BASE_DIR / "output" / "fhir"
34
  os.makedirs(SYNTHEA_DATA_DIR, exist_ok=True)
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  async def process_synthea_patient(bundle: dict, file_path: str) -> Optional[dict]:
37
  logger.debug(f"Processing patient from file: {file_path}")
38
  patient_data = {}
@@ -276,7 +346,7 @@ async def import_patients(
276
  detail=f"Import failed: {str(e)}"
277
  )
278
 
279
- @router.get("/patients", response_model=List[dict])
280
  async def list_patients(
281
  search: Optional[str] = Query(None),
282
  min_notes: int = Query(0, ge=0),
@@ -285,7 +355,7 @@ async def list_patients(
285
  skip: int = Query(0, ge=0)
286
  ):
287
  logger.info(f"Listing patients with search: {search}, limit: {limit}, skip: {skip}")
288
- query = {"source": "synthea"}
289
 
290
  if search:
291
  query["$or"] = [
@@ -310,7 +380,8 @@ async def list_patients(
310
  "conditions": 1,
311
  "medications": 1,
312
  "encounters": 1,
313
- "notes": 1
 
314
  }
315
 
316
  try:
@@ -330,6 +401,7 @@ async def list_patients(
330
  "medications": patient.get("medications", []),
331
  "encounters": patient.get("encounters", []),
332
  "notes": patient.get("notes", []),
 
333
  "age": calculate_age(patient.get("date_of_birth")),
334
  "stats": {
335
  "notes": len(patient.get("notes", [])),
@@ -348,7 +420,7 @@ async def list_patients(
348
  detail=f"Failed to retrieve patients: {str(e)}"
349
  )
350
 
351
- @router.get("/patients/{patient_id}", response_model=dict)
352
  async def get_patient(patient_id: str):
353
  logger.info(f"Retrieving patient: {patient_id}")
354
  try:
@@ -413,7 +485,7 @@ async def get_patient(patient_id: str):
413
  detail=f"Failed to retrieve patient: {str(e)}"
414
  )
415
 
416
- @router.post("/patients/{patient_id}/notes", status_code=status.HTTP_201_CREATED)
417
  async def add_note(
418
  patient_id: str,
419
  note: Note,
 
1
+ from fastapi import APIRouter, HTTPException, Depends, Query, status, Body
2
  from db.mongo import patients_collection
3
  from core.security import get_current_user
4
  from utils.db import create_indexes
5
  from utils.helpers import calculate_age, standardize_language
6
+ from models.entities import Note, PatientCreate
7
  from datetime import datetime
8
  from bson import ObjectId
9
  from bson.errors import InvalidId
 
33
  SYNTHEA_DATA_DIR = BASE_DIR / "output" / "fhir"
34
  os.makedirs(SYNTHEA_DATA_DIR, exist_ok=True)
35
 
36
+ @router.post("/", status_code=status.HTTP_201_CREATED)
37
+ async def create_patient(
38
+ patient_data: PatientCreate,
39
+ current_user: dict = Depends(get_current_user)
40
+ ):
41
+ """
42
+ Create a new patient in the database.
43
+
44
+ Args:
45
+ patient_data: Patient data to be created
46
+ current_user: Authenticated user making the request
47
+
48
+ Returns:
49
+ The created patient data with generated IDs
50
+ """
51
+ logger.info(f"Creating new patient by user {current_user.get('email')}")
52
+
53
+ if current_user.get('role') not in ['admin', 'doctor']:
54
+ logger.warning(f"Unauthorized create attempt by {current_user.get('email')}")
55
+ raise HTTPException(
56
+ status_code=status.HTTP_403_FORBIDDEN,
57
+ detail="Only administrators and doctors can create patients"
58
+ )
59
+
60
+ try:
61
+ # Prepare the patient document
62
+ patient_doc = patient_data.dict()
63
+ now = datetime.utcnow().isoformat()
64
+
65
+ # Add system-generated fields
66
+ patient_doc.update({
67
+ "fhir_id": str(uuid.uuid4()),
68
+ "import_date": now,
69
+ "last_updated": now,
70
+ "source": "manual"
71
+ })
72
+
73
+ # Ensure arrays exist even if empty
74
+ for field in ['conditions', 'medications', 'encounters', 'notes']:
75
+ if field not in patient_doc:
76
+ patient_doc[field] = []
77
+
78
+ # Insert the patient document
79
+ result = await patients_collection.insert_one(patient_doc)
80
+
81
+ # Return the created patient with the generated ID
82
+ created_patient = await patients_collection.find_one(
83
+ {"_id": result.inserted_id}
84
+ )
85
+
86
+ if not created_patient:
87
+ logger.error("Failed to retrieve created patient")
88
+ raise HTTPException(
89
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
90
+ detail="Failed to retrieve created patient"
91
+ )
92
+
93
+ created_patient["id"] = str(created_patient["_id"])
94
+ del created_patient["_id"]
95
+
96
+ logger.info(f"Successfully created patient {created_patient['fhir_id']}")
97
+ return created_patient
98
+
99
+ except Exception as e:
100
+ logger.error(f"Failed to create patient: {str(e)}")
101
+ raise HTTPException(
102
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
103
+ detail=f"Failed to create patient: {str(e)}"
104
+ )
105
+
106
  async def process_synthea_patient(bundle: dict, file_path: str) -> Optional[dict]:
107
  logger.debug(f"Processing patient from file: {file_path}")
108
  patient_data = {}
 
346
  detail=f"Import failed: {str(e)}"
347
  )
348
 
349
+ @router.get("/", response_model=List[dict])
350
  async def list_patients(
351
  search: Optional[str] = Query(None),
352
  min_notes: int = Query(0, ge=0),
 
355
  skip: int = Query(0, ge=0)
356
  ):
357
  logger.info(f"Listing patients with search: {search}, limit: {limit}, skip: {skip}")
358
+ query = {}
359
 
360
  if search:
361
  query["$or"] = [
 
380
  "conditions": 1,
381
  "medications": 1,
382
  "encounters": 1,
383
+ "notes": 1,
384
+ "source": 1
385
  }
386
 
387
  try:
 
401
  "medications": patient.get("medications", []),
402
  "encounters": patient.get("encounters", []),
403
  "notes": patient.get("notes", []),
404
+ "source": patient.get("source", "unknown"),
405
  "age": calculate_age(patient.get("date_of_birth")),
406
  "stats": {
407
  "notes": len(patient.get("notes", [])),
 
420
  detail=f"Failed to retrieve patients: {str(e)}"
421
  )
422
 
423
+ @router.get("/{patient_id}", response_model=dict)
424
  async def get_patient(patient_id: str):
425
  logger.info(f"Retrieving patient: {patient_id}")
426
  try:
 
485
  detail=f"Failed to retrieve patient: {str(e)}"
486
  )
487
 
488
+ @router.post("/{patient_id}/notes", status_code=status.HTTP_201_CREATED)
489
  async def add_note(
490
  patient_id: str,
491
  note: Note,