Skip to content

Commit b370d53

Browse files
committed
Add user machine query
1 parent 9f0d731 commit b370d53

4 files changed

Lines changed: 66 additions & 1 deletion

File tree

app/api/v1/users.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from datetime import UTC, datetime
2+
from decimal import Decimal
23

34
from fastapi import APIRouter, Depends, HTTPException, Query
45
from passlib.context import CryptContext
6+
from sqlalchemy import func
57
from sqlalchemy.orm import Session
68

79
from app.auth.deps import get_current_device, require_admin_user, require_checkout_device, require_session_user
@@ -10,13 +12,15 @@
1012
from app.database import get_db
1113
from app.models.machine import Machine, MachineAuthorization
1214
from app.models.rental import Rental
15+
from app.models.session import MachineSession
1316
from app.models.transaction import Transaction
1417
from app.models.user import User
1518
from app.schemas.common import MessageResponse
1619
from app.schemas.transaction import MeTransactionResponse
1720
from app.schemas.user import (
1821
LinkTokenResponse, UserAuthResponse, UserCreate, UserLinkOidc,
19-
UserMeMachineResponse, UserMeRentalResponse, UserResponse, UserUpdate,
22+
UserMeMachineResponse, UserMeRentalResponse, UserMeSessionResponse,
23+
UserResponse, UserUpdate,
2024
)
2125

2226
router = APIRouter()
@@ -126,6 +130,51 @@ def get_me_machines(
126130
]
127131

128132

133+
@router.get("/me/sessions", response_model=list[UserMeSessionResponse])
134+
def get_me_sessions(
135+
limit: int = Query(default=10, ge=1, le=100),
136+
offset: int = Query(default=0, ge=0),
137+
user: dict = Depends(require_session_user),
138+
db: Session = Depends(get_db),
139+
):
140+
"""Machine session history for the logged-in user, newest first."""
141+
db_user = _me_user(user, db)
142+
sessions = (
143+
db.query(MachineSession)
144+
.filter(MachineSession.user_id == db_user.id)
145+
.order_by(MachineSession.start_time.desc())
146+
.offset(offset)
147+
.limit(limit)
148+
.all()
149+
)
150+
151+
costs: dict[int, Decimal] = {}
152+
session_ids = [s.id for s in sessions]
153+
if session_ids:
154+
for sid, total in (
155+
db.query(Transaction.session_id, func.sum(Transaction.amount))
156+
.filter(Transaction.session_id.in_(session_ids))
157+
.group_by(Transaction.session_id)
158+
.all()
159+
):
160+
costs[sid] = Decimal(str(total or 0))
161+
162+
result = []
163+
for s in sessions:
164+
duration = int((s.end_time - s.start_time).total_seconds()) if s.end_time else None
165+
cost = max(-costs.get(s.id, Decimal("0.00")), Decimal("0.00"))
166+
result.append(UserMeSessionResponse(
167+
id=s.id,
168+
machine_name=s.machine.name,
169+
machine_slug=s.machine.slug,
170+
start_time=s.start_time,
171+
end_time=s.end_time,
172+
duration_seconds=duration,
173+
total_cost=cost,
174+
))
175+
return result
176+
177+
129178
# ---------------------------------------------------------------------------
130179
# Device endpoints
131180
# ---------------------------------------------------------------------------

app/schemas/user.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,13 @@ class UserMeMachineResponse(BaseModel):
7474
price_per_login: Decimal = Field(ge=0, examples=[Decimal("0.00")])
7575
price_per_minute: Decimal = Field(ge=0, examples=[Decimal("0.05")])
7676
booking_interval: int
77+
78+
79+
class UserMeSessionResponse(BaseModel):
80+
id: int
81+
machine_name: str
82+
machine_slug: str
83+
start_time: datetime
84+
end_time: Optional[datetime]
85+
duration_seconds: Optional[int]
86+
total_cost: Decimal = Field(ge=0, examples=[Decimal("1.50")])

app/web/locales/de.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@
258258
"me.type_admin": "Anpassung",
259259
"me.col_rented_since": "Seit",
260260
"me.col_per_min": "Tarif",
261+
"me.sessions_title": "Maschinensitzungen",
262+
"me.sessions_empty": "Noch keine Maschinensitzungen.",
263+
"me.sessions_machine": "Maschine",
261264

262265
"connect.title_success": "Karte verknüpft",
263266
"connect.title_failure": "Verknüpfung fehlgeschlagen",

app/web/locales/en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@
258258
"me.type_admin": "Adjustment",
259259
"me.col_rented_since": "Since",
260260
"me.col_per_min": "Rate",
261+
"me.sessions_title": "Machine Sessions",
262+
"me.sessions_empty": "No machine sessions yet.",
263+
"me.sessions_machine": "Machine",
261264

262265
"connect.title_success": "Card Linked",
263266
"connect.title_failure": "Link Failed",

0 commit comments

Comments
 (0)