# app/services/slot_snapshot_service.py from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from redis.asyncio import Redis from app.models.slot_snapshot import VasSlotSnapshot from app.schemas.slot_snapshot import SlotSnapshotCreate, SlotSnapshotOut from app.services.notification_service import NotificationService class SlotSnapshotService: @staticmethod async def report( db: AsyncSession, redis_client: Redis, data: SlotSnapshotCreate ) -> VasSlotSnapshot: rec = VasSlotSnapshot(**data.dict()) db.add(rec) await db.commit() await db.refresh(rec) # 修复点在这里:手动将 datetime 对象转为 string earliest_date_str = rec.earliest_date.isoformat() if rec.earliest_date else None snapshot_at_str = rec.snapshot_at.isoformat() if rec.snapshot_at else None await NotificationService.post_wechat( redis_client=redis_client, template_id="slot_snapshot", payload={ "country": rec.country, "city": rec.city, "visa_type": rec.visa_type, "routing_key": rec.routing_key, "availability_status": rec.availability_status, # 使用转换后的字符串 "earliest_date": earliest_date_str, "availability": rec.availability, "snapshot_source": rec.snapshot_source, "snapshot_at": snapshot_at_str } ) return rec @staticmethod async def latest_for( db: AsyncSession, country: str, city: str, visa_type: str ) -> VasSlotSnapshot: stmt = ( select(VasSlotSnapshot) .where( VasSlotSnapshot.country == country, VasSlotSnapshot.city == city, VasSlotSnapshot.visa_type == visa_type, ) .order_by(VasSlotSnapshot.snapshot_at.desc()) .limit(1) ) return await db.scalar(stmt)