""" Beacon Service - 蓝牙信标管理服务 Provides CRUD operations for Bluetooth beacon configuration. """ from datetime import datetime, timezone from sqlalchemy import func, select, or_ from sqlalchemy.ext.asyncio import AsyncSession from app.models import BeaconConfig from app.schemas import BeaconConfigCreate, BeaconConfigUpdate async def get_beacons( db: AsyncSession, page: int = 1, page_size: int = 20, status_filter: str | None = None, search: str | None = None, ) -> tuple[list[BeaconConfig], int]: """Get paginated beacon list with optional filters.""" query = select(BeaconConfig) count_query = select(func.count(BeaconConfig.id)) if status_filter: query = query.where(BeaconConfig.status == status_filter) count_query = count_query.where(BeaconConfig.status == status_filter) if search: like = f"%{search}%" cond = or_( BeaconConfig.beacon_mac.ilike(like), BeaconConfig.name.ilike(like), BeaconConfig.area.ilike(like), ) query = query.where(cond) count_query = count_query.where(cond) total_result = await db.execute(count_query) total = total_result.scalar() or 0 offset = (page - 1) * page_size query = query.order_by(BeaconConfig.created_at.desc()).offset(offset).limit(page_size) result = await db.execute(query) return list(result.scalars().all()), total async def get_beacon(db: AsyncSession, beacon_id: int) -> BeaconConfig | None: result = await db.execute( select(BeaconConfig).where(BeaconConfig.id == beacon_id) ) return result.scalar_one_or_none() async def get_beacon_by_mac(db: AsyncSession, mac: str) -> BeaconConfig | None: result = await db.execute( select(BeaconConfig).where(BeaconConfig.beacon_mac == mac) ) return result.scalar_one_or_none() async def create_beacon(db: AsyncSession, data: BeaconConfigCreate) -> BeaconConfig: beacon = BeaconConfig(**data.model_dump()) db.add(beacon) await db.flush() await db.refresh(beacon) return beacon async def update_beacon( db: AsyncSession, beacon_id: int, data: BeaconConfigUpdate ) -> BeaconConfig | None: beacon = await get_beacon(db, beacon_id) if beacon is None: return None update_data = data.model_dump(exclude_unset=True) for key, value in update_data.items(): setattr(beacon, key, value) from app.config import now_cst beacon.updated_at = now_cst() await db.flush() await db.refresh(beacon) return beacon async def delete_beacon(db: AsyncSession, beacon_id: int) -> bool: beacon = await get_beacon(db, beacon_id) if beacon is None: return False await db.delete(beacon) await db.flush() return True