hisham-cmd commited on
Commit
47c29c1
Β·
verified Β·
1 Parent(s): d937179

Upload app/api/notifications.py

Browse files
Files changed (1) hide show
  1. app/api/notifications.py +122 -0
app/api/notifications.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, Depends, HTTPException
2
+ from sqlalchemy.orm import Session
3
+ from pydantic import BaseModel
4
+ from typing import Optional
5
+ from datetime import datetime, timezone
6
+
7
+ from app.db.base import get_db
8
+ from app.models.notification import Notification
9
+ from app.api.auth import get_current_user
10
+ from app.models.user import User
11
+
12
+ router = APIRouter(prefix="/notifications", tags=["Notifications"])
13
+
14
+
15
+ # ── Schemas ───────────────────────────────────────────────────
16
+ class NotificationCreate(BaseModel):
17
+ type: str # checkout_shipping | checkout_payment | checkout_complete
18
+ title: str
19
+ message: Optional[str] = None
20
+ data: Optional[dict] = None
21
+
22
+
23
+ class NotificationOut(BaseModel):
24
+ id: int
25
+ type: str
26
+ title: str
27
+ message: Optional[str]
28
+ data: Optional[dict]
29
+ is_read: bool
30
+ created_at: datetime
31
+
32
+ class Config:
33
+ from_attributes = True
34
+
35
+
36
+ # ── POST /notifications β€” create (no auth, called from checkout) ──
37
+ @router.post("/")
38
+ async def create_notification(payload: NotificationCreate, db: Session = Depends(get_db)):
39
+ notif = Notification(
40
+ type=payload.type,
41
+ title=payload.title,
42
+ message=payload.message,
43
+ data=payload.data,
44
+ is_read=False,
45
+ created_at=datetime.now(timezone.utc),
46
+ )
47
+ db.add(notif)
48
+ db.commit()
49
+ db.refresh(notif)
50
+ return {
51
+ "isSuccess": True,
52
+ "value": {"id": notif.id},
53
+ "statusCode": 201,
54
+ }
55
+
56
+
57
+ # ── GET /notifications β€” list for admin ──
58
+ @router.get("/")
59
+ async def list_notifications(
60
+ skip: int = 0,
61
+ limit: int = 50,
62
+ unread_only: bool = False,
63
+ current_user: User = Depends(get_current_user),
64
+ db: Session = Depends(get_db),
65
+ ):
66
+ if current_user.role.upper() != "ADMIN":
67
+ raise HTTPException(status_code=403, detail="Admin access required")
68
+
69
+ query = db.query(Notification)
70
+ if unread_only:
71
+ query = query.filter(Notification.is_read == False) # noqa: E712
72
+ query = query.order_by(Notification.created_at.desc())
73
+
74
+ total = query.count()
75
+ notifications = query.offset(skip).limit(limit).all()
76
+
77
+ return {
78
+ "isSuccess": True,
79
+ "value": {
80
+ "notifications": [
81
+ NotificationOut.model_validate(n).model_dump() for n in notifications
82
+ ],
83
+ "total": total,
84
+ "unread_count": db.query(Notification).filter(Notification.is_read == False).count(), # noqa: E712
85
+ },
86
+ "statusCode": 200,
87
+ }
88
+
89
+
90
+ # ── PUT /notifications/{id}/read β€” mark single as read ──
91
+ @router.put("/{notification_id}/read")
92
+ async def mark_read(
93
+ notification_id: int,
94
+ current_user: User = Depends(get_current_user),
95
+ db: Session = Depends(get_db),
96
+ ):
97
+ if current_user.role.upper() != "ADMIN":
98
+ raise HTTPException(status_code=403, detail="Admin access required")
99
+
100
+ notif = db.query(Notification).filter(Notification.id == notification_id).first()
101
+ if not notif:
102
+ raise HTTPException(status_code=404, detail="Notification not found")
103
+
104
+ notif.is_read = True
105
+ db.commit()
106
+ return {"isSuccess": True, "value": None, "statusCode": 200}
107
+
108
+
109
+ # ── PUT /notifications/read-all β€” mark all as read ──
110
+ @router.put("/read-all")
111
+ async def mark_all_read(
112
+ current_user: User = Depends(get_current_user),
113
+ db: Session = Depends(get_db),
114
+ ):
115
+ if current_user.role.upper() != "ADMIN":
116
+ raise HTTPException(status_code=403, detail="Admin access required")
117
+
118
+ db.query(Notification).filter(Notification.is_read == False).update( # noqa: E712
119
+ {"is_read": True}
120
+ )
121
+ db.commit()
122
+ return {"isSuccess": True, "value": None, "statusCode": 200}