Files
badoHair_be/app/routers/admin/bookings.py
belviskhoremk d2dc43b16f Initial Commit
2026-05-12 00:34:21 +00:00

180 lines
5.6 KiB
Python

from datetime import date
from typing import Annotated
from fastapi import APIRouter, Depends, Query
import asyncpg
from app.core.pagination import pagination_params
from app.core.responses import ok, paginated
from app.dependencies import get_db, require_admin
from app.models.bookings import (
UpdateBookingStatus, SlotCreate, WeeklyScheduleCreate,
GenerateSlotsRequest, BlockedDateCreate, UpdateSlotRequest,
)
from app.services import booking_service, slot_service
router = APIRouter(tags=["Admin — Bookings"])
# ── Bookings ──────────────────────────────────────────────────────────────────
@router.get("/bookings")
async def list_bookings(
pagination: Annotated[tuple, Depends(pagination_params)],
status: str | None = Query(None),
from_date: date | None = Query(None),
to_date: date | None = Query(None),
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
page, per_page, offset = pagination
bookings, total = await booking_service.list_bookings(
db, page, per_page, offset,
status=status, from_date=from_date, to_date=to_date,
)
return paginated(bookings, total, page, per_page)
@router.get("/bookings/{booking_id}")
async def get_booking(
booking_id: str,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
booking = await booking_service.get_booking(db, booking_id)
return ok(booking)
@router.patch("/bookings/{booking_id}")
async def update_booking(
booking_id: str,
body: UpdateBookingStatus,
db: asyncpg.Connection = Depends(get_db),
admin: dict = Depends(require_admin),
):
booking = await booking_service.admin_update_booking(
db, booking_id, body.status, body.admin_notes, str(admin["id"])
)
return ok(booking)
@router.delete("/bookings/{booking_id}", status_code=204)
async def delete_booking(
booking_id: str,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
await booking_service.admin_delete_booking(db, booking_id)
# ── Slots ─────────────────────────────────────────────────────────────────────
@router.get("/slots")
async def list_slots(
from_date: date = Query(...),
to_date: date = Query(...),
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
slots = await slot_service.list_slots(db, from_date, to_date, available_only=False)
return ok(slots)
@router.post("/slots", status_code=201)
async def create_slot(
body: SlotCreate,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
slot = await slot_service.create_slot(db, body)
return ok(slot)
@router.patch("/slots/{slot_id}")
async def update_slot(
slot_id: str,
body: UpdateSlotRequest,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
slot = await slot_service.update_slot(db, slot_id, body.is_blocked, body.block_reason)
return ok(slot)
@router.delete("/slots/{slot_id}", status_code=204)
async def delete_slot(
slot_id: str,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
await slot_service.delete_slot(db, slot_id)
@router.post("/slots/generate")
async def generate_slots(
body: GenerateSlotsRequest,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
created = await slot_service.generate_slots(db, body.from_date, body.to_date)
return ok({"created": created})
# ── Weekly schedule ───────────────────────────────────────────────────────────
@router.get("/schedule")
async def get_schedule(
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
schedule = await slot_service.get_schedule(db)
return ok(schedule)
@router.post("/schedule", status_code=201)
async def create_schedule(
body: WeeklyScheduleCreate,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
entry = await slot_service.create_schedule_entry(db, body)
return ok(entry)
@router.delete("/schedule/{schedule_id}", status_code=204)
async def delete_schedule(
schedule_id: str,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
await slot_service.delete_schedule_entry(db, schedule_id)
# ── Blocked dates ─────────────────────────────────────────────────────────────
@router.get("/blocked-dates")
async def get_blocked_dates(
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
dates = await slot_service.get_blocked_dates(db)
return ok(dates)
@router.post("/blocked-dates", status_code=201)
async def add_blocked_date(
body: BlockedDateCreate,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
entry = await slot_service.add_blocked_date(db, body.date, body.reason)
return ok(entry)
@router.delete("/blocked-dates/{blocked_date_id}", status_code=204)
async def remove_blocked_date(
blocked_date_id: str,
db: asyncpg.Connection = Depends(get_db),
_: dict = Depends(require_admin),
):
await slot_service.remove_blocked_date(db, blocked_date_id)