Ali2206 commited on
Commit
b7721ca
·
verified ·
1 Parent(s): b09d7f8

Update api/routes.py

Browse files
Files changed (1) hide show
  1. api/routes.py +28 -166
api/routes.py CHANGED
@@ -1,4 +1,4 @@
1
- from fastapi import APIRouter, HTTPException, Depends, Body, UploadFile, File
2
  from fastapi.security import OAuth2PasswordRequestForm
3
  from models.schemas import SignupForm, TokenResponse, PatientCreate, DoctorCreate, AppointmentCreate
4
  from db.mongo import users_collection, patients_collection, appointments_collection
@@ -8,10 +8,7 @@ from bson import ObjectId
8
  from bson.errors import InvalidId
9
  from typing import Optional, List
10
  from pydantic import BaseModel
11
- from pathlib import Path
12
- import csv
13
- import io
14
- import json
15
 
16
  router = APIRouter()
17
 
@@ -134,176 +131,41 @@ async def list_patients(current_user: dict = Depends(get_current_user)):
134
  })
135
  return patients
136
 
137
- # --- COUNT PATIENTS ---
138
- @router.get("/patients-count")
139
- async def count_patients(current_user: dict = Depends(get_current_user)):
140
- if current_user.get("role") != "doctor":
141
- raise HTTPException(status_code=403, detail="Only doctors can count patients")
142
- count = await patients_collection.count_documents({"created_by": current_user["email"]})
143
- return {"count": count}
144
-
145
- # --- CREATE APPOINTMENT ---
146
- @router.post("/appointments")
147
- async def create_appointment(data: AppointmentCreate, current_user: dict = Depends(get_current_user)):
148
- if current_user.get("role") != "patient":
149
- raise HTTPException(status_code=403, detail="Only patients can book appointments")
150
-
151
- patient_user = await users_collection.find_one({"email": current_user["email"]})
152
- if not patient_user:
153
- raise HTTPException(status_code=404, detail="Patient user not found")
154
-
155
- appointment_doc = {
156
- "patient_id": patient_user["_id"],
157
- "doctor_id": ObjectId(data.doctor_id),
158
- "date": datetime.combine(data.date, datetime.min.time()),
159
- "time": data.time.strftime("%H:%M:%S"),
160
- "reason": data.reason,
161
- "created_by": current_user["email"],
162
- "created_at": datetime.utcnow()
163
- }
164
- await appointments_collection.insert_one(appointment_doc)
165
-
166
- return {"message": "Appointment booked successfully"}
167
-
168
- # --- LIST DOCTOR'S APPOINTMENTS ---
169
- @router.get("/appointments/doctor")
170
- async def list_doctor_appointments(current_user: dict = Depends(get_current_user)):
171
- if current_user.get("role") != "doctor":
172
- raise HTTPException(status_code=403, detail="Only doctors can view this")
173
-
174
- cursor = appointments_collection.find({"doctor_id": ObjectId(current_user["_id"])})
175
- appointments = []
176
- async for a in cursor:
177
- try:
178
- patient_id = a.get("patient_id")
179
- if not isinstance(patient_id, ObjectId):
180
- patient_id = ObjectId(patient_id)
181
- patient = await users_collection.find_one({"_id": patient_id})
182
- except Exception:
183
- patient = None
184
-
185
- appointments.append({
186
- "_id": str(a["_id"]),
187
- "doctor_id": str(a["doctor_id"]),
188
- "patient": {
189
- "full_name": patient.get("full_name", "Unknown") if patient else "Unknown",
190
- "email": patient.get("email", "") if patient else "",
191
- },
192
- "date": a.get("date").strftime("%Y-%m-%d") if isinstance(a.get("date"), datetime) else a.get("date"),
193
- "time": a.get("time", ""),
194
- "reason": a.get("reason", "")
195
- })
196
-
197
- return appointments
198
-
199
- # --- LIST PATIENT'S APPOINTMENTS ---
200
- @router.get("/appointments/patient")
201
- async def list_my_appointments(current_user: dict = Depends(get_current_user)):
202
- if current_user.get("role") != "patient":
203
- raise HTTPException(status_code=403, detail="Only patients can view their appointments")
204
-
205
- user = await users_collection.find_one({"email": current_user["email"]})
206
- if not user:
207
- raise HTTPException(status_code=404, detail="User not found")
208
-
209
- patient_id = user.get("_id")
210
- cursor = appointments_collection.find({"patient_id": patient_id})
211
- return [{**a, "_id": str(a["_id"]), "patient_id": str(a["patient_id"]), "doctor_id": str(a["doctor_id"])} async for a in cursor]
212
-
213
- # === UTIL: Parse Synthea CSV ===
214
- def parse_synthea_patient_csv(file: UploadFile) -> List[dict]:
215
- decoded = file.file.read().decode("utf-8")
216
- reader = csv.DictReader(io.StringIO(decoded))
217
- patients = []
218
-
219
- for row in reader:
220
- patients.append({
221
- "synthea_id": row.get("Id"),
222
- "full_name": f"{row.get('FIRST', '')} {row.get('LAST', '')}".strip(),
223
- "gender": row.get("GENDER"),
224
- "date_of_birth": datetime.strptime(row.get("BIRTHDATE"), "%Y-%m-%dT%H:%M:%SZ"),
225
- "address": row.get("ADDRESS"),
226
- "city": row.get("CITY"),
227
- "state": row.get("STATE"),
228
- "zip": row.get("ZIP"),
229
- "created_at": datetime.utcnow()
230
- })
231
-
232
- return patients
233
-
234
- # === API: Upload and import patients.csv ===
235
- @router.post("/ehr/import-patients")
236
- async def import_synthea_patients(file: UploadFile = File(...)):
237
- if not file.filename.endswith(".csv"):
238
- raise HTTPException(status_code=400, detail="Only CSV files are supported")
239
 
240
  try:
241
- patients = parse_synthea_patient_csv(file)
242
- result = await patients_collection.insert_many(patients)
243
- return {"inserted_count": len(result.inserted_ids)}
244
- except Exception as e:
245
- raise HTTPException(status_code=500, detail=str(e))
246
 
247
- # === GET all Synthea patients ===
248
- @router.get("/ehr/synthea-patients")
249
- async def list_synthea_patients():
250
- cursor = patients_collection.find({"synthea_id": {"$exists": True}})
251
- patients = []
252
- async for p in cursor:
253
- patients.append({
254
- "id": str(p["_id"]),
255
- "synthea_id": p.get("synthea_id"),
256
- "full_name": p.get("full_name"),
257
- "gender": p.get("gender"),
258
- "date_of_birth": p.get("date_of_birth"),
259
- })
260
- return patients
261
 
262
- # === GET individual Synthea patient ===
263
- @router.get("/ehr/synthea-patient/{id}")
264
- async def get_synthea_patient(id: str):
265
- try:
266
- patient = await patients_collection.find_one({"_id": ObjectId(id)})
267
- if not patient:
268
- raise HTTPException(status_code=404, detail="Patient not found")
269
- patient["id"] = str(patient["_id"])
270
- del patient["_id"]
271
- return patient
272
- except Exception:
273
- raise HTTPException(status_code=400, detail="Invalid patient ID")
274
-
275
-
276
-
277
- @router.post("/ehr/auto-import")
278
- async def auto_import_synthea_patients():
279
- csv_path = Path("data/synthea/patients.csv")
280
 
281
- if not csv_path.exists():
282
- raise HTTPException(status_code=404, detail="Synthea patients.csv not found.")
283
-
284
- try:
285
- with open(csv_path, "r", encoding="utf-8") as f:
286
- reader = csv.DictReader(f)
287
- patients = []
288
 
289
- for row in reader:
290
- patients.append({
291
- "synthea_id": row.get("Id"),
292
- "full_name": f"{row.get('FIRST', '')} {row.get('LAST', '')}".strip(),
293
- "gender": row.get("GENDER"),
294
- "date_of_birth": datetime.strptime(row.get("BIRTHDATE"), "%Y-%m-%dT%H:%M:%SZ"),
295
- "address": row.get("ADDRESS"),
296
- "city": row.get("CITY"),
297
- "state": row.get("STATE"),
298
- "zip": row.get("ZIP"),
299
- "created_at": datetime.utcnow()
300
- })
301
 
302
- if not patients:
303
- raise HTTPException(status_code=400, detail="No patients found in CSV.")
 
 
 
 
 
 
304
 
305
  result = await patients_collection.insert_many(patients)
306
- return {"message": "Imported successfully", "count": len(result.inserted_ids)}
307
 
308
  except Exception as e:
309
  raise HTTPException(status_code=500, detail=str(e))
 
1
+ from fastapi import APIRouter, HTTPException, Depends, Body
2
  from fastapi.security import OAuth2PasswordRequestForm
3
  from models.schemas import SignupForm, TokenResponse, PatientCreate, DoctorCreate, AppointmentCreate
4
  from db.mongo import users_collection, patients_collection, appointments_collection
 
8
  from bson.errors import InvalidId
9
  from typing import Optional, List
10
  from pydantic import BaseModel
11
+ import httpx
 
 
 
12
 
13
  router = APIRouter()
14
 
 
131
  })
132
  return patients
133
 
134
+ # --- IMPORT FROM PUBLIC FHIR API ---
135
+ @router.post("/ehr/fetch-from-api")
136
+ async def fetch_and_store_patients_from_fhir():
137
+ fhir_api = "https://hapi.fhir.org/baseR4/Patient?_count=50"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
  try:
140
+ async with httpx.AsyncClient() as client:
141
+ response = await client.get(fhir_api)
 
 
 
142
 
143
+ if response.status_code != 200:
144
+ raise HTTPException(status_code=502, detail="Failed to fetch from FHIR server.")
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
+ data = response.json()
147
+ entries = data.get("entry", [])
148
+ if not entries:
149
+ return {"message": "No patients found."}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
+ patients = []
 
 
 
 
 
 
152
 
153
+ for entry in entries:
154
+ resource = entry.get("resource", {})
155
+ name = resource.get("name", [{}])[0]
156
+ full_name = f"{name.get('given', [''])[0]} {name.get('family', '')}".strip()
 
 
 
 
 
 
 
 
157
 
158
+ patient = {
159
+ "fhir_id": resource.get("id"),
160
+ "full_name": full_name,
161
+ "gender": resource.get("gender"),
162
+ "date_of_birth": resource.get("birthDate"),
163
+ "created_at": datetime.utcnow()
164
+ }
165
+ patients.append(patient)
166
 
167
  result = await patients_collection.insert_many(patients)
168
+ return {"message": "Fetched and stored successfully", "count": len(result.inserted_ids)}
169
 
170
  except Exception as e:
171
  raise HTTPException(status_code=500, detail=str(e))