Ali2206 commited on
Commit
7d320f0
·
verified ·
1 Parent(s): 2ba25dc

Update api/routes.py

Browse files
Files changed (1) hide show
  1. api/routes.py +40 -110
api/routes.py CHANGED
@@ -1,6 +1,6 @@
1
  from fastapi import APIRouter, HTTPException, Depends, Body
2
  from fastapi.security import OAuth2PasswordRequestForm
3
- from models.schemas import SignupForm, TokenResponse, PatientCreate
4
  from db.mongo import users_collection, patients_collection
5
  from core.security import hash_password, verify_password, create_access_token, get_current_user
6
  from datetime import datetime
@@ -11,9 +11,12 @@ from pydantic import BaseModel
11
 
12
  router = APIRouter()
13
 
14
- # --- SIGNUP ---
15
  @router.post("/signup")
16
  async def signup(data: SignupForm):
 
 
 
17
  email = data.email.lower().strip()
18
  existing = await users_collection.find_one({"email": email})
19
  if existing:
@@ -24,10 +27,30 @@ async def signup(data: SignupForm):
24
  "email": email,
25
  "full_name": data.full_name.strip(),
26
  "password": hashed_pw,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  "created_at": datetime.utcnow()
28
  }
29
  await users_collection.insert_one(user_doc)
30
- return {"success": True, "message": "Account created"}
31
 
32
  # --- LOGIN ---
33
  @router.post("/login", response_model=TokenResponse)
@@ -46,17 +69,19 @@ async def get_me(current_user: dict = Depends(get_current_user)):
46
  return {
47
  "email": current_user["email"],
48
  "full_name": current_user.get("full_name", ""),
 
49
  "created_at": current_user.get("created_at", "")
50
  }
51
 
52
  # --- ADD NEW PATIENT ---
53
  @router.post("/patients")
54
  async def add_patient(data: PatientCreate, current_user: dict = Depends(get_current_user)):
 
 
 
55
  patient_doc = {
56
- "full_name": data.full_name,
57
  "date_of_birth": datetime.combine(data.date_of_birth, datetime.min.time()),
58
- "gender": data.gender,
59
- "notes": data.notes,
60
  "contact": data.contact.dict() if data.contact else {},
61
  "created_by": current_user["email"],
62
  "created_at": datetime.utcnow()
@@ -67,6 +92,9 @@ async def add_patient(data: PatientCreate, current_user: dict = Depends(get_curr
67
  # --- GET ALL PATIENTS ---
68
  @router.get("/patients")
69
  async def list_patients(current_user: dict = Depends(get_current_user)):
 
 
 
70
  patients_cursor = patients_collection.find({"created_by": current_user["email"]})
71
  patients = []
72
  async for patient in patients_cursor:
@@ -75,113 +103,15 @@ async def list_patients(current_user: dict = Depends(get_current_user)):
75
  "full_name": patient.get("full_name", ""),
76
  "date_of_birth": patient.get("date_of_birth"),
77
  "gender": patient.get("gender", ""),
78
- "notes": patient.get("notes", ""),
79
  })
80
  return patients
81
 
82
- # --- GET PATIENT BY ID ---
83
- @router.get("/patients/{patient_id}")
84
- async def get_patient_by_id(patient_id: str, current_user: dict = Depends(get_current_user)):
85
- try:
86
- patient = await patients_collection.find_one({
87
- "_id": ObjectId(patient_id),
88
- "created_by": current_user["email"]
89
- })
90
- except InvalidId:
91
- raise HTTPException(status_code=400, detail="Invalid patient ID")
92
-
93
- if not patient:
94
- raise HTTPException(status_code=404, detail="Patient not found")
95
-
96
- return {
97
- "id": str(patient["_id"]),
98
- "full_name": patient.get("full_name", ""),
99
- "date_of_birth": patient.get("date_of_birth"),
100
- "gender": patient.get("gender", ""),
101
- "notes": patient.get("notes", ""),
102
- "contact": patient.get("contact", {}),
103
- "created_at": patient.get("created_at"),
104
- }
105
-
106
- # --- UPDATE PATIENT ---
107
- class PatientUpdate(BaseModel):
108
- full_name: Optional[str]
109
- date_of_birth: Optional[datetime]
110
- gender: Optional[str]
111
- notes: Optional[str]
112
- contact: Optional[dict]
113
-
114
- @router.put("/patients/{patient_id}")
115
- async def update_patient(
116
- patient_id: str,
117
- data: PatientUpdate = Body(...),
118
- current_user: dict = Depends(get_current_user)
119
- ):
120
- try:
121
- oid = ObjectId(patient_id)
122
- except InvalidId:
123
- raise HTTPException(status_code=400, detail="Invalid patient ID")
124
-
125
- update_data = {}
126
- for key, value in data.dict(exclude_unset=True).items():
127
- if key == "date_of_birth" and value:
128
- update_data[key] = datetime.combine(value, datetime.min.time())
129
- else:
130
- update_data[key] = value
131
-
132
- result = await patients_collection.update_one(
133
- {"_id": oid, "created_by": current_user["email"]},
134
- {"$set": update_data}
135
- )
136
-
137
- if result.matched_count == 0:
138
- raise HTTPException(status_code=404, detail="Patient not found")
139
-
140
- return {"message": "Patient updated successfully"}
141
-
142
- # --- DELETE PATIENT ---
143
- @router.delete("/patients/{patient_id}")
144
- async def delete_patient(patient_id: str, current_user: dict = Depends(get_current_user)):
145
- try:
146
- oid = ObjectId(patient_id)
147
- except InvalidId:
148
- raise HTTPException(status_code=400, detail="Invalid patient ID")
149
-
150
- result = await patients_collection.delete_one({
151
- "_id": oid,
152
- "created_by": current_user["email"]
153
- })
154
-
155
- if result.deleted_count == 0:
156
- raise HTTPException(status_code=404, detail="Patient not found or unauthorized")
157
-
158
- return {"message": "Patient deleted successfully"}
159
-
160
  # --- COUNT PATIENTS BY DOCTOR ---
161
- @router.get("/patients-count") # ✅ No chance of conflict
162
  async def count_patients(current_user: dict = Depends(get_current_user)):
163
- try:
164
- email = current_user.get("email")
165
- print("📌 Authenticated user email:", email)
166
-
167
- if not email or not isinstance(email, str):
168
- print("❗ Email missing or invalid:", email)
169
- raise HTTPException(status_code=400, detail="Invalid user email")
170
-
171
- if patients_collection is None:
172
- print("❌ patients_collection is None")
173
- raise HTTPException(status_code=500, detail="Database not connected")
174
-
175
- filter_query = {"created_by": email}
176
- print("🔍 Running count_documents with:", filter_query)
177
-
178
- count = await patients_collection.count_documents(filter_query)
179
-
180
- print("✅ Count result:", count)
181
- return {"count": count}
182
 
183
- except Exception as e:
184
- import traceback
185
- traceback.print_exc()
186
- print("❌ ERROR in /patients/count:", repr(e))
187
- raise HTTPException(status_code=500, detail="Internal Server Error")
 
1
  from fastapi import APIRouter, HTTPException, Depends, Body
2
  from fastapi.security import OAuth2PasswordRequestForm
3
+ from models.schemas import SignupForm, TokenResponse, PatientCreate, DoctorCreate
4
  from db.mongo import users_collection, patients_collection
5
  from core.security import hash_password, verify_password, create_access_token, get_current_user
6
  from datetime import datetime
 
11
 
12
  router = APIRouter()
13
 
14
+ # --- SIGNUP (for patients only) ---
15
  @router.post("/signup")
16
  async def signup(data: SignupForm):
17
+ if data.role != "patient":
18
+ raise HTTPException(status_code=403, detail="Only patients can sign up via this route")
19
+
20
  email = data.email.lower().strip()
21
  existing = await users_collection.find_one({"email": email})
22
  if existing:
 
27
  "email": email,
28
  "full_name": data.full_name.strip(),
29
  "password": hashed_pw,
30
+ "role": "patient",
31
+ "created_at": datetime.utcnow()
32
+ }
33
+ await users_collection.insert_one(user_doc)
34
+ return {"success": True, "message": "Patient account created"}
35
+
36
+ # --- ADMIN: Create doctor account ---
37
+ @router.post("/admin/create-doctor")
38
+ async def create_doctor(data: DoctorCreate):
39
+ existing = await users_collection.find_one({"email": data.email})
40
+ if existing:
41
+ raise HTTPException(status_code=409, detail="Email already exists")
42
+
43
+ hashed_pw = hash_password(data.password)
44
+ user_doc = {
45
+ "matricule": data.matricule,
46
+ "email": data.email.lower().strip(),
47
+ "full_name": data.full_name.strip(),
48
+ "password": hashed_pw,
49
+ "role": "doctor",
50
  "created_at": datetime.utcnow()
51
  }
52
  await users_collection.insert_one(user_doc)
53
+ return {"success": True, "message": "Doctor account created"}
54
 
55
  # --- LOGIN ---
56
  @router.post("/login", response_model=TokenResponse)
 
69
  return {
70
  "email": current_user["email"],
71
  "full_name": current_user.get("full_name", ""),
72
+ "role": current_user.get("role", "unknown"),
73
  "created_at": current_user.get("created_at", "")
74
  }
75
 
76
  # --- ADD NEW PATIENT ---
77
  @router.post("/patients")
78
  async def add_patient(data: PatientCreate, current_user: dict = Depends(get_current_user)):
79
+ if current_user.get("role") != "doctor":
80
+ raise HTTPException(status_code=403, detail="Only doctors can add patients")
81
+
82
  patient_doc = {
83
+ **data.dict(),
84
  "date_of_birth": datetime.combine(data.date_of_birth, datetime.min.time()),
 
 
85
  "contact": data.contact.dict() if data.contact else {},
86
  "created_by": current_user["email"],
87
  "created_at": datetime.utcnow()
 
92
  # --- GET ALL PATIENTS ---
93
  @router.get("/patients")
94
  async def list_patients(current_user: dict = Depends(get_current_user)):
95
+ if current_user.get("role") != "doctor":
96
+ raise HTTPException(status_code=403, detail="Only doctors can view patients")
97
+
98
  patients_cursor = patients_collection.find({"created_by": current_user["email"]})
99
  patients = []
100
  async for patient in patients_cursor:
 
103
  "full_name": patient.get("full_name", ""),
104
  "date_of_birth": patient.get("date_of_birth"),
105
  "gender": patient.get("gender", ""),
106
+ "notes": patient.get("notes", "")
107
  })
108
  return patients
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  # --- COUNT PATIENTS BY DOCTOR ---
111
+ @router.get("/patients-count")
112
  async def count_patients(current_user: dict = Depends(get_current_user)):
113
+ if current_user.get("role") != "doctor":
114
+ raise HTTPException(status_code=403, detail="Only doctors can count patients")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
+ count = await patients_collection.count_documents({"created_by": current_user["email"]})
117
+ return {"count": count}