Hp137 commited on
Commit
5c780f1
·
1 Parent(s): 84b9f8f

feat:added profile service

Browse files
Files changed (3) hide show
  1. src/auth/router.py +26 -2
  2. src/profile/router.py +124 -26
  3. src/profile/schemas.py +23 -0
src/auth/router.py CHANGED
@@ -11,7 +11,8 @@ from src.auth.service import (
11
  login_user,
12
  )
13
  from src.auth.utils import get_current_user
14
- from src.core.models import Users
 
15
  from src.core.config import settings
16
  from fastapi.responses import RedirectResponse
17
  from .schemas import SignUpRequest, LoginRequest, BaseResponse, SendVerificationRequest
@@ -63,6 +64,21 @@ async def login(
63
  payload: LoginRequest, session: AsyncSession = Depends(get_async_session)
64
  ):
65
  response = await login_user(session, payload.email, payload.password)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  return {"code": 200, "data": response}
67
 
68
 
@@ -104,6 +120,13 @@ async def get_home(
104
  if not user:
105
  raise HTTPException(status_code=404, detail="User not found")
106
 
 
 
 
 
 
 
 
107
  # Example payload — replace with your real app data
108
  return {
109
  "code": 200,
@@ -115,7 +138,8 @@ async def get_home(
115
  "email": user.email_id,
116
  "is_verified": user.is_verified,
117
  "dob": user.dob.isoformat() if user.dob else None,
118
- "profile_picture": user.profile_picture
 
119
  },
120
  "home_data": {
121
  "announcements": ["Welcome!", "New protocol released"],
 
11
  login_user,
12
  )
13
  from src.auth.utils import get_current_user
14
+ from src.core.models import Users, Roles, UserTeamsRole
15
+ from sqlmodel import select
16
  from src.core.config import settings
17
  from fastapi.responses import RedirectResponse
18
  from .schemas import SignUpRequest, LoginRequest, BaseResponse, SendVerificationRequest
 
64
  payload: LoginRequest, session: AsyncSession = Depends(get_async_session)
65
  ):
66
  response = await login_user(session, payload.email, payload.password)
67
+
68
+ user_id = response["user"]["id"]
69
+
70
+ # 🔥 Fetch User Role
71
+ result = await session.exec(
72
+ select(Roles)
73
+ .join(UserTeamsRole, UserTeamsRole.role_id == Roles.id)
74
+ .where(UserTeamsRole.user_id == uuid.UUID(user_id))
75
+ )
76
+
77
+ role_obj = result.first()
78
+ role_name = role_obj.name if role_obj else "Member"
79
+
80
+ response["user"]["role"] = (role_name or "member").lower()
81
+
82
  return {"code": 200, "data": response}
83
 
84
 
 
120
  if not user:
121
  raise HTTPException(status_code=404, detail="User not found")
122
 
123
+ role_join = await session.exec(
124
+ select(Roles.name)
125
+ .join(UserTeamsRole, UserTeamsRole.role_id == Roles.id)
126
+ .where(UserTeamsRole.user_id == uuid.UUID(user_id))
127
+ )
128
+ user_role = role_join.first() or "Member"
129
+
130
  # Example payload — replace with your real app data
131
  return {
132
  "code": 200,
 
138
  "email": user.email_id,
139
  "is_verified": user.is_verified,
140
  "dob": user.dob.isoformat() if user.dob else None,
141
+ "profile_picture": user.profile_picture,
142
+ "role": user_role.lower(),
143
  },
144
  "home_data": {
145
  "announcements": ["Welcome!", "New protocol released"],
src/profile/router.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from src.core.database import get_async_session
2
  from src.auth.utils import get_current_user
3
  from src.profile.models import Leave, LeaveType, LeaveStatus
@@ -76,8 +77,6 @@ async def mentor_decision_route(
76
  detail="Comment is required when rejecting leave",
77
  )
78
 
79
-
80
-
81
  try:
82
  leave = await mentor_decide_leave(session, mentor_uuid, leave_uuid, body)
83
  except PermissionError as e:
@@ -212,33 +211,42 @@ async def list_notifications(
212
  return {"code": 200, "data": notifications}
213
 
214
 
215
- @router.get("/leave/{leave_id}")
216
  async def get_leave_details(
217
  leave_id: str,
218
  session: AsyncSession = Depends(get_async_session),
219
  user_id: str = Depends(get_current_user),
220
  ):
221
- leave = await session.get(Leave, leave_id)
 
 
 
 
 
222
 
223
- if not leave:
 
 
224
  raise HTTPException(status_code=404, detail="Leave not found")
225
 
226
- # Convert to JSON response
 
227
  return {
228
  "code": 200,
229
  "data": {
230
  "id": str(leave.id),
231
  "user_id": str(leave.user_id),
 
232
  "mentor_id": str(leave.mentor_id),
233
  "lead_id": str(leave.lead_id),
234
  "leave_type": leave.leave_type,
235
- "from_date": str(leave.from_date),
236
- "to_date": str(leave.to_date),
237
  "days": leave.days,
238
  "reason": leave.reason,
239
  "status": leave.status,
240
  "reject_reason": leave.reject_reason,
241
- "updated_at": leave.updated_at.isoformat(),
242
  },
243
  }
244
 
@@ -248,32 +256,122 @@ async def mentor_pending_leaves(
248
  session: AsyncSession = Depends(get_async_session),
249
  mentor_id: str = Depends(get_current_user),
250
  ):
251
- stmt = select(Leave).where(
252
- Leave.mentor_id == mentor_id,
253
- Leave.status == LeaveStatus.PENDING,
 
 
 
 
 
 
254
  )
255
 
256
  rows = (await session.exec(stmt)).all()
257
 
258
- return {
259
- "code": 200,
260
- "data": [
 
261
  LeaveResponse(
262
- id=str(r.id),
263
- leave_type=r.leave_type,
264
- from_date=r.from_date,
265
- to_date=r.to_date,
266
- days=r.days,
267
- reason=r.reason,
268
- status=r.status,
269
- mentor_id=str(r.mentor_id),
270
- lead_id=str(r.lead_id),
 
 
 
 
 
 
 
 
 
 
271
  )
272
- for r in rows
273
- ],
 
 
 
274
  }
275
 
276
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  @router.get("/contacts", response_model=BaseResponse)
278
  async def get_leave_contacts(
279
  current_user=Depends(get_current_user),
 
1
+ from src.profile.schemas import LeaveDetailResponse
2
  from src.core.database import get_async_session
3
  from src.auth.utils import get_current_user
4
  from src.profile.models import Leave, LeaveType, LeaveStatus
 
77
  detail="Comment is required when rejecting leave",
78
  )
79
 
 
 
80
  try:
81
  leave = await mentor_decide_leave(session, mentor_uuid, leave_uuid, body)
82
  except PermissionError as e:
 
211
  return {"code": 200, "data": notifications}
212
 
213
 
214
+ @router.get("/leave/{leave_id}", response_model=LeaveDetailResponse)
215
  async def get_leave_details(
216
  leave_id: str,
217
  session: AsyncSession = Depends(get_async_session),
218
  user_id: str = Depends(get_current_user),
219
  ):
220
+ # Join Leave + Users table to get user_name
221
+ stmt = (
222
+ select(Leave, Users.user_name)
223
+ .join(Users, Users.id == Leave.user_id)
224
+ .where(Leave.id == uuid.UUID(leave_id))
225
+ )
226
 
227
+ row = (await session.exec(stmt)).first()
228
+
229
+ if not row:
230
  raise HTTPException(status_code=404, detail="Leave not found")
231
 
232
+ leave, user_name = row
233
+
234
  return {
235
  "code": 200,
236
  "data": {
237
  "id": str(leave.id),
238
  "user_id": str(leave.user_id),
239
+ "user_name": user_name,
240
  "mentor_id": str(leave.mentor_id),
241
  "lead_id": str(leave.lead_id),
242
  "leave_type": leave.leave_type,
243
+ "from_date": leave.from_date.isoformat(),
244
+ "to_date": leave.to_date.isoformat(),
245
  "days": leave.days,
246
  "reason": leave.reason,
247
  "status": leave.status,
248
  "reject_reason": leave.reject_reason,
249
+ "updated_at": leave.updated_at.isoformat() if leave.updated_at else None,
250
  },
251
  }
252
 
 
256
  session: AsyncSession = Depends(get_async_session),
257
  mentor_id: str = Depends(get_current_user),
258
  ):
259
+ print("🔥 mentor pending called for:", mentor_id)
260
+
261
+ stmt = (
262
+ select(Leave, Users.user_name)
263
+ .join(Users, Users.id == Leave.user_id)
264
+ .where(
265
+ Leave.mentor_id == uuid.UUID(mentor_id),
266
+ Leave.status == LeaveStatus.PENDING,
267
+ )
268
  )
269
 
270
  rows = (await session.exec(stmt)).all()
271
 
272
+ result = []
273
+
274
+ for leave, user_name in rows:
275
+ result.append(
276
  LeaveResponse(
277
+ id=str(leave.id),
278
+ leave_type=leave.leave_type,
279
+ from_date=leave.from_date.isoformat(),
280
+ to_date=leave.to_date.isoformat(),
281
+ days=leave.days,
282
+ reason=leave.reason,
283
+ status=(
284
+ leave.status.value
285
+ if hasattr(leave.status, "value")
286
+ else leave.status
287
+ ),
288
+ mentor_id=str(leave.mentor_id),
289
+ lead_id=str(leave.lead_id),
290
+ user_name=user_name,
291
+ updated_at=(
292
+ leave.updated_at.isoformat()
293
+ if hasattr(leave, "updated_at") and leave.updated_at
294
+ else None
295
+ ),
296
  )
297
+ )
298
+
299
+ return {
300
+ "code": 200,
301
+ "data": result,
302
  }
303
 
304
 
305
+ @router.get("/my-leaves")
306
+ async def my_leave_history(
307
+ session: AsyncSession = Depends(get_async_session),
308
+ user_id: str = Depends(get_current_user),
309
+ ):
310
+ stmt = (
311
+ select(Leave, Users.user_name, Users.email_id)
312
+ .join(Users, Users.id == Leave.mentor_id, isouter=True)
313
+ .where(Leave.user_id == uuid.UUID(user_id))
314
+ .order_by(desc(Leave.updated_at))
315
+ )
316
+
317
+ rows = (await session.exec(stmt)).all()
318
+
319
+ result = []
320
+ for leave, mentor_name, mentor_email in rows:
321
+ result.append(
322
+ {
323
+ "id": str(leave.id),
324
+ "leave_type": leave.leave_type,
325
+ "from_date": leave.from_date.isoformat(),
326
+ "to_date": leave.to_date.isoformat(),
327
+ "days": leave.days,
328
+ "reason": leave.reason,
329
+ "status": leave.status,
330
+ "mentor_name": mentor_name,
331
+ "updated_at": (
332
+ leave.updated_at.isoformat() if leave.updated_at else None
333
+ ),
334
+ }
335
+ )
336
+
337
+ return {"code": 200, "data": result}
338
+
339
+
340
+ @router.get("/mentor/team-leaves")
341
+ async def team_leave_history(
342
+ session: AsyncSession = Depends(get_async_session),
343
+ mentor_id: str = Depends(get_current_user),
344
+ ):
345
+ stmt = (
346
+ select(Leave, Users.user_name)
347
+ .join(Users, Users.id == Leave.user_id)
348
+ .where(Leave.mentor_id == uuid.UUID(mentor_id))
349
+ .order_by(desc(Leave.updated_at))
350
+ )
351
+
352
+ rows = (await session.exec(stmt)).all()
353
+
354
+ result = []
355
+ for leave, username in rows:
356
+ result.append(
357
+ {
358
+ "id": str(leave.id),
359
+ "user_name": username,
360
+ "leave_type": leave.leave_type,
361
+ "from_date": leave.from_date.isoformat(),
362
+ "to_date": leave.to_date.isoformat(),
363
+ "days": leave.days,
364
+ "reason": leave.reason,
365
+ "status": leave.status,
366
+ "updated_at": (
367
+ leave.updated_at.isoformat() if leave.updated_at else None
368
+ ),
369
+ }
370
+ )
371
+
372
+ return {"code": 200, "data": result}
373
+
374
+
375
  @router.get("/contacts", response_model=BaseResponse)
376
  async def get_leave_contacts(
377
  current_user=Depends(get_current_user),
src/profile/schemas.py CHANGED
@@ -31,6 +31,27 @@ class ApproveRejectRequest(BaseModel):
31
  comment: Optional[str] = None # optional for approve, required for reject
32
 
33
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  class LeaveResponse(BaseModel):
35
  id: str
36
  leave_type: LeaveType
@@ -41,6 +62,8 @@ class LeaveResponse(BaseModel):
41
  status: LeaveStatus
42
  mentor_id: str
43
  lead_id: str
 
 
44
 
45
 
46
  class DeviceTokenIn(BaseModel):
 
31
  comment: Optional[str] = None # optional for approve, required for reject
32
 
33
 
34
+ class LeaveDetail(BaseModel):
35
+ id: str
36
+ user_id: str
37
+ user_name: str # 👈 NEW FIELD
38
+ mentor_id: Optional[str]
39
+ lead_id: Optional[str]
40
+ leave_type: str
41
+ from_date: str
42
+ to_date: str
43
+ days: int
44
+ reason: str
45
+ status: str
46
+ reject_reason: Optional[str]
47
+ updated_at: Optional[str]
48
+
49
+
50
+ class LeaveDetailResponse(BaseModel):
51
+ code: int
52
+ data: LeaveDetail
53
+
54
+
55
  class LeaveResponse(BaseModel):
56
  id: str
57
  leave_type: LeaveType
 
62
  status: LeaveStatus
63
  mentor_id: str
64
  lead_id: str
65
+ user_name: Optional[str] = None
66
+ updated_at: Optional[str] = None
67
 
68
 
69
  class DeviceTokenIn(BaseModel):