dylanglenister commited on
Commit
4624a2d
·
1 Parent(s): a00215a

Unifying doctors and users routes as accounts

Browse files
src/api/routes/{doctors.py → account.py} RENAMED
@@ -1,61 +1,61 @@
1
- # api/routes/doctors.py
2
 
3
  from fastapi import APIRouter, HTTPException
4
 
5
- from src.data.repositories.account import (create_account, get_all_accounts,
6
- get_account_by_name, search_accounts)
7
- from src.models.user import DoctorCreateRequest
8
  from src.utils.logger import logger
9
 
10
- router = APIRouter(prefix="/doctors", tags=["Doctors"])
11
 
12
  @router.get("")
13
- async def get_all_doctors_route(limit: int = 50):
14
  try:
15
- logger().info(f"GET /doctors limit={limit}")
16
  results = get_all_accounts(limit=limit)
17
- logger().info(f"Retrieved {len(results)} doctors")
18
  return {"results": results}
19
  except Exception as e:
20
- logger().error(f"Error getting all doctors: {e}")
21
  raise HTTPException(status_code=500, detail=str(e))
22
 
23
  @router.post("")
24
- async def create_doctor_profile(req: DoctorCreateRequest):
25
  try:
26
- logger().info(f"POST /doctors name={req.name}")
27
- doctor_id = create_account(
28
  name=req.name,
29
  role=req.role,
30
  specialty=req.specialty
31
  )
32
- logger().info(f"Created doctor {req.name} id={doctor_id}")
33
- return {"doctor_id": doctor_id, "name": req.name}
34
  except Exception as e:
35
- logger().error(f"Error creating doctor: {e}")
36
  raise HTTPException(status_code=500, detail=str(e))
37
 
38
- @router.get("/{doctor_name}")
39
- async def get_doctor(doctor_name: str):
40
  try:
41
- logger().info(f"GET /doctors/{doctor_name}")
42
- doctor = get_account_by_name(doctor_name)
43
- if not doctor:
44
- raise HTTPException(status_code=404, detail="Doctor not found")
45
- return doctor
46
  except HTTPException:
47
  raise
48
  except Exception as e:
49
- logger().error(f"Error getting doctor: {e}")
50
  raise HTTPException(status_code=500, detail=str(e))
51
 
52
  @router.get("/search")
53
- async def search_doctors_route(q: str, limit: int = 10):
54
  try:
55
- logger().info(f"GET /doctors/search q='{q}' limit={limit}")
56
  results = search_accounts(q, limit=limit)
57
- logger().info(f"Doctor search returned {len(results)} results")
58
  return {"results": results}
59
  except Exception as e:
60
- logger().error(f"Error searching doctors: {e}")
61
  raise HTTPException(status_code=500, detail=str(e))
 
1
+ # api/routes/account.py
2
 
3
  from fastapi import APIRouter, HTTPException
4
 
5
+ from src.data.repositories.account import (create_account, get_account_by_name,
6
+ get_all_accounts, search_accounts)
7
+ from src.models.user import AccountCreateRequest
8
  from src.utils.logger import logger
9
 
10
+ router = APIRouter(prefix="/account", tags=["Account"])
11
 
12
  @router.get("")
13
+ async def get_all_accounts_route(limit: int = 50):
14
  try:
15
+ logger(tag="All").info(f"GET /account limit={limit}")
16
  results = get_all_accounts(limit=limit)
17
+ logger().info(f"Retrieved {len(results)} accounts")
18
  return {"results": results}
19
  except Exception as e:
20
+ logger().error(f"Error getting all accounts: {e}")
21
  raise HTTPException(status_code=500, detail=str(e))
22
 
23
  @router.post("")
24
+ async def create_account_profile(req: AccountCreateRequest):
25
  try:
26
+ logger().info(f"POST /account name={req.name}")
27
+ account_id = create_account(
28
  name=req.name,
29
  role=req.role,
30
  specialty=req.specialty
31
  )
32
+ logger().info(f"Created account {req.name} id={account_id}")
33
+ return {"account_id": account_id, "name": req.name}
34
  except Exception as e:
35
+ logger().error(f"Error creating account: {e}")
36
  raise HTTPException(status_code=500, detail=str(e))
37
 
38
+ @router.get("/{account_name}")
39
+ async def get_account(account_name: str):
40
  try:
41
+ logger(tag="By name").info(f"GET /account/{account_name}")
42
+ account = get_account_by_name(account_name)
43
+ if not account:
44
+ raise HTTPException(status_code=404, detail="account not found")
45
+ return account
46
  except HTTPException:
47
  raise
48
  except Exception as e:
49
+ logger().error(f"Error getting account: {e}")
50
  raise HTTPException(status_code=500, detail=str(e))
51
 
52
  @router.get("/search")
53
+ async def search_accounts_route(q: str, limit: int = 10):
54
  try:
55
+ logger().info(f"GET /account/search q='{q}' limit={limit}")
56
  results = search_accounts(q, limit=limit)
57
+ logger().info(f"account search returned {len(results)} results")
58
  return {"results": results}
59
  except Exception as e:
60
+ logger().error(f"Error searching accounts: {e}")
61
  raise HTTPException(status_code=500, detail=str(e))
src/api/routes/user.py DELETED
@@ -1,72 +0,0 @@
1
- # api/routes/user.py
2
-
3
- from fastapi import APIRouter, Depends, HTTPException
4
-
5
- from src.core.state import MedicalState, get_state
6
- from src.data.repositories.account import create_account
7
- from src.models.user import UserProfileRequest
8
- from src.utils.logger import logger
9
-
10
- router = APIRouter(prefix="/users", tags=["Users"])
11
-
12
- @router.post("")
13
- async def create_user_profile(
14
- request: UserProfileRequest,
15
- state: MedicalState = Depends(get_state)
16
- ):
17
- """Create or update user profile"""
18
- try:
19
- # Persist to in-memory profile (existing behavior)
20
- #state.memory_system.create_user(name=request.name, role=request.role, speciality=request.specialty)
21
-
22
- # Persist to MongoDB accounts collection
23
- account_id = create_account(
24
- request.name,
25
- request.role,
26
- request.specialty
27
- )
28
-
29
- return {"message": "User profile created successfully", "account_id": account_id}
30
- except Exception as e:
31
- logger().error(f"Error creating user profile: {e}")
32
- raise HTTPException(status_code=500, detail=str(e))
33
-
34
- @router.get("/{user_id}")
35
- async def get_user_profile(
36
- user_id: str,
37
- state: MedicalState = Depends(get_state)
38
- ):
39
- """Get user profile and sessions"""
40
- try:
41
- user = state.memory_system.get_user(user_id)
42
- if not user:
43
- raise HTTPException(status_code=404, detail="User not found")
44
-
45
- sessions = state.memory_system.get_user_sessions(user_id)
46
-
47
- return {
48
- "user": {
49
- "id": user.user_id,
50
- "name": user.name,
51
- "role": user.preferences.get("role", "Unknown"),
52
- "specialty": user.preferences.get("specialty", ""),
53
- "medical_roles": user.preferences.get("medical_roles", []),
54
- "created_at": user.created_at,
55
- "last_seen": user.last_seen
56
- },
57
- "sessions": [
58
- {
59
- "id": session.session_id,
60
- "title": session.title,
61
- "created_at": session.created_at,
62
- "last_activity": session.last_activity,
63
- "message_count": len(session.messages)
64
- }
65
- for session in sessions if session is not None
66
- ]
67
- }
68
- except HTTPException:
69
- raise
70
- except Exception as e:
71
- logger().error(f"Error getting user profile: {e}")
72
- raise HTTPException(status_code=500, detail=str(e))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/data/repositories/account.py CHANGED
@@ -39,6 +39,7 @@ VALID_ROLES = [
39
  ]
40
 
41
  def create():
 
42
  create_collection(
43
  ACCOUNTS_COLLECTION,
44
  "schemas/account_validator.json"
@@ -68,7 +69,7 @@ def create_account(
68
  user_data: dict[str, Any] = {
69
  "name": name,
70
  "role" : role,
71
- "specialty": specialty,
72
  "created_at": now,
73
  "updated_at": now
74
  }
@@ -120,10 +121,12 @@ def get_account(
120
 
121
  def get_account_by_name(name: str) -> dict[str, Any] | None:
122
  """Get account by name from accounts collection"""
 
123
  collection = get_collection(ACCOUNTS_COLLECTION)
124
  account = collection.find_one({"name": name})
125
- #if account:
126
- # account["_id"] = str(account.get("_id")) if account.get("_id") else None
 
127
  return account
128
 
129
  def search_accounts(query: str, limit: int = 10) -> list[dict[str, Any]]:
 
39
  ]
40
 
41
  def create():
42
+ #get_collection(ACCOUNTS_COLLECTION).drop()
43
  create_collection(
44
  ACCOUNTS_COLLECTION,
45
  "schemas/account_validator.json"
 
69
  user_data: dict[str, Any] = {
70
  "name": name,
71
  "role" : role,
72
+ "specialty": specialty or "",
73
  "created_at": now,
74
  "updated_at": now
75
  }
 
121
 
122
  def get_account_by_name(name: str) -> dict[str, Any] | None:
123
  """Get account by name from accounts collection"""
124
+ logger().info("Trying to retrieve account: " + name)
125
  collection = get_collection(ACCOUNTS_COLLECTION)
126
  account = collection.find_one({"name": name})
127
+ # HACK This somehow stops some unusual bug with creating a new account.
128
+ if account:
129
+ account["_id"] = str(account.get("_id")) if account.get("_id") else None
130
  return account
131
 
132
  def search_accounts(query: str, limit: int = 10) -> list[dict[str, Any]]:
src/main.py CHANGED
@@ -24,14 +24,13 @@ except Exception as e:
24
  logger(tag="env").warning(f"Error loading .env file: {e}")
25
 
26
  # Import project modules after trying to load environment variables
 
27
  from src.api.routes import audio as audio_route
28
  from src.api.routes import chat as chat_route
29
- from src.api.routes import doctors as doctors_route
30
  from src.api.routes import patients as patients_route
31
  from src.api.routes import session as session_route
32
  from src.api.routes import static as static_route
33
  from src.api.routes import system as system_route
34
- from src.api.routes import user as user_route
35
  from src.core.state import MedicalState, get_state
36
  from src.data.repositories import account as account_repo
37
  from src.data.repositories import medical as medical_repo
@@ -124,10 +123,9 @@ app.mount("/static", StaticFiles(directory="static"), name="static")
124
 
125
  # Include routers
126
  app.include_router(chat_route.router)
127
- app.include_router(user_route.router)
128
  app.include_router(session_route.router)
129
  app.include_router(patients_route.router)
130
- app.include_router(doctors_route.router)
131
  app.include_router(system_route.router)
132
  app.include_router(static_route.router)
133
  app.include_router(audio_route.router)
 
24
  logger(tag="env").warning(f"Error loading .env file: {e}")
25
 
26
  # Import project modules after trying to load environment variables
27
+ from src.api.routes import account as account_route
28
  from src.api.routes import audio as audio_route
29
  from src.api.routes import chat as chat_route
 
30
  from src.api.routes import patients as patients_route
31
  from src.api.routes import session as session_route
32
  from src.api.routes import static as static_route
33
  from src.api.routes import system as system_route
 
34
  from src.core.state import MedicalState, get_state
35
  from src.data.repositories import account as account_repo
36
  from src.data.repositories import medical as medical_repo
 
123
 
124
  # Include routers
125
  app.include_router(chat_route.router)
 
126
  app.include_router(session_route.router)
127
  app.include_router(patients_route.router)
128
+ app.include_router(account_route.router)
129
  app.include_router(system_route.router)
130
  app.include_router(static_route.router)
131
  app.include_router(audio_route.router)
src/models/user.py CHANGED
@@ -3,12 +3,7 @@
3
  from pydantic import BaseModel
4
 
5
 
6
- class UserProfileRequest(BaseModel):
7
- name: str
8
- role: str
9
- specialty: str | None = None
10
-
11
- class DoctorCreateRequest(BaseModel):
12
  name: str
13
  role: str
14
  specialty: str | None = None
 
3
  from pydantic import BaseModel
4
 
5
 
6
+ class AccountCreateRequest(BaseModel):
 
 
 
 
 
7
  name: str
8
  role: str
9
  specialty: str | None = None
static/js/app.js CHANGED
@@ -599,7 +599,7 @@ How can I assist you today?`;
599
  } else {
600
  // If doctor not found in local list, try to fetch from backend
601
  try {
602
- const resp = await fetch(`/doctors/search?q=${encodeURIComponent(selectedName)}&limit=1`);
603
  if (resp.ok) {
604
  const data = await resp.json();
605
  const doctor = data.results && data.results[0];
@@ -968,7 +968,7 @@ How can I assist you today?`;
968
  async loadDoctors() {
969
  try {
970
  // Fetch doctors from MongoDB
971
- const resp = await fetch('/doctors');
972
  if (resp.ok) {
973
  const data = await resp.json();
974
  this.doctors = data.results || [];
@@ -1004,7 +1004,7 @@ How can I assist you today?`;
1004
 
1005
  async searchDoctors(query) {
1006
  try {
1007
- const resp = await fetch(`/doctors/search?q=${encodeURIComponent(query)}&limit=10`);
1008
  if (resp.ok) {
1009
  const data = await resp.json();
1010
  return data.results || [];
@@ -1017,7 +1017,7 @@ How can I assist you today?`;
1017
 
1018
  async createDoctor(doctorData) {
1019
  try {
1020
- const resp = await fetch('/doctors', {
1021
  method: 'POST',
1022
  headers: { 'Content-Type': 'application/json' },
1023
  body: JSON.stringify(doctorData)
@@ -1134,7 +1134,7 @@ How can I assist you today?`;
1134
  // Check if doctor exists in MongoDB first
1135
  let doctorExists = false;
1136
  try {
1137
- const resp = await fetch(`/doctors/${encodeURIComponent(name)}`);
1138
  doctorExists = resp.ok;
1139
  } catch (e) {
1140
  console.warn('Failed to check doctor existence:', e);
@@ -1176,7 +1176,7 @@ How can I assist you today?`;
1176
  };
1177
 
1178
  try {
1179
- const resp = await fetch('/doctors', {
1180
  method: 'POST',
1181
  headers: { 'Content-Type': 'application/json' },
1182
  body: JSON.stringify(doctorPayload)
 
599
  } else {
600
  // If doctor not found in local list, try to fetch from backend
601
  try {
602
+ const resp = await fetch(`/account/search?q=${encodeURIComponent(selectedName)}&limit=1`);
603
  if (resp.ok) {
604
  const data = await resp.json();
605
  const doctor = data.results && data.results[0];
 
968
  async loadDoctors() {
969
  try {
970
  // Fetch doctors from MongoDB
971
+ const resp = await fetch('/account');
972
  if (resp.ok) {
973
  const data = await resp.json();
974
  this.doctors = data.results || [];
 
1004
 
1005
  async searchDoctors(query) {
1006
  try {
1007
+ const resp = await fetch(`/account/search?q=${encodeURIComponent(query)}&limit=10`);
1008
  if (resp.ok) {
1009
  const data = await resp.json();
1010
  return data.results || [];
 
1017
 
1018
  async createDoctor(doctorData) {
1019
  try {
1020
+ const resp = await fetch('/account', {
1021
  method: 'POST',
1022
  headers: { 'Content-Type': 'application/json' },
1023
  body: JSON.stringify(doctorData)
 
1134
  // Check if doctor exists in MongoDB first
1135
  let doctorExists = false;
1136
  try {
1137
+ const resp = await fetch(`/account/${encodeURIComponent(name)}`);
1138
  doctorExists = resp.ok;
1139
  } catch (e) {
1140
  console.warn('Failed to check doctor existence:', e);
 
1176
  };
1177
 
1178
  try {
1179
+ const resp = await fetch('/account', {
1180
  method: 'POST',
1181
  headers: { 'Content-Type': 'application/json' },
1182
  body: JSON.stringify(doctorPayload)