""" 佣金结算单API路由 """ from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy import select, func, and_, or_ from sqlalchemy.ext.asyncio import AsyncSession from loguru import logger from app.database import get_async_session from app.models.settlement import Settlement from app.schemas.settlement import ( SettlementCreate, SettlementUpdate, SettlementResponse, SettlementListResponse, ) router = APIRouter() @router.get("", response_model=SettlementListResponse) async def list_settlements( page: int = Query(1, ge=1, description="页码"), size: int = Query(10, ge=1, le=100, description="每页数量"), settlement_id: str = Query(None, description="结算单ID"), streamer_id: str = Query(None, description="主播ID"), payment_status: str = Query(None, description="付款状态"), settlement_status: str = Query(None, description="结算状态"), db: AsyncSession = Depends(get_async_session), ): """ 获取佣金结算单列表(分页查询) """ logger.info(f"获取佣金结算单列表: page={page}, size={size}") # 构建查询 query = select(Settlement) # 添加过滤条件 conditions = [] if settlement_id: conditions.append(Settlement.settlement_id.ilike(f"%{settlement_id}%")) if streamer_id: conditions.append(Settlement.streamer_id == streamer_id) if payment_status: conditions.append(Settlement.payment_status == payment_status) if settlement_status: conditions.append(Settlement.settlement_status == settlement_status) if conditions: query = query.where(and_(*conditions)) # 获取总数 count_query = select(func.count()).select_from(Settlement) if conditions: count_query = count_query.where(and_(*conditions)) total_result = await db.execute(count_query) total = total_result.scalar() # 分页 query = query.offset((page - 1) * size).limit(size) # 执行查询 result = await db.execute(query) records = result.scalars().all() # 转换为响应格式 response_records = [] for settlement in records: response_records.append({ "id": settlement.id, "settlement_id": settlement.settlement_id, "settlement_no": settlement.settlement_no, "streamer_id": settlement.streamer_id, "streamer_name": settlement.streamer_name, "streamer_entity_type": settlement.streamer_entity_type, "settlement_period": settlement.settlement_period, "settlement_start_date": settlement.settlement_start_date.isoformat() if settlement.settlement_start_date else None, "settlement_end_date": settlement.settlement_end_date.isoformat() if settlement.settlement_end_date else None, "order_count": settlement.order_count, "total_sales": settlement.total_sales, "total_commission": settlement.total_commission, "platform_service_fee": settlement.platform_service_fee, "actual_settlement_amount": settlement.actual_settlement_amount, "tax_withholding": settlement.tax_withholding, "payment_method": settlement.payment_method, "payment_account_no": settlement.payment_account_no, "payment_account_name": settlement.payment_account_name, "payment_time": settlement.payment_time.isoformat() if settlement.payment_time else None, "payment_status": settlement.payment_status, "settlement_status": settlement.settlement_status, "remark": settlement.remark, }) return SettlementListResponse( records=response_records, total=total, page=page, size=size, ) @router.get("/{settlement_id}", response_model=SettlementResponse) async def get_settlement(settlement_id: str, db: AsyncSession = Depends(get_async_session)): """ 根据ID获取佣金结算单详细信息 """ logger.info(f"获取佣金结算单详情: {settlement_id}") query = select(Settlement).where(Settlement.settlement_id == settlement_id) result = await db.execute(query) settlement = result.scalar_one_or_none() if not settlement: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"佣金结算单不存在: {settlement_id}", ) # 转换为响应格式 response = { "id": settlement.id, "settlement_id": settlement.settlement_id, "settlement_no": settlement.settlement_no, "streamer_id": settlement.streamer_id, "streamer_name": settlement.streamer_name, "streamer_entity_type": settlement.streamer_entity_type, "settlement_period": settlement.settlement_period, "settlement_start_date": settlement.settlement_start_date.isoformat() if settlement.settlement_start_date else None, "settlement_end_date": settlement.settlement_end_date.isoformat() if settlement.settlement_end_date else None, "order_count": settlement.order_count, "total_sales": settlement.total_sales, "total_commission": settlement.total_commission, "platform_service_fee": settlement.platform_service_fee, "actual_settlement_amount": settlement.actual_settlement_amount, "tax_withholding": settlement.tax_withholding, "payment_method": settlement.payment_method, "payment_account_no": settlement.payment_account_no, "payment_account_name": settlement.payment_account_name, "payment_time": settlement.payment_time.isoformat() if settlement.payment_time else None, "payment_status": settlement.payment_status, "settlement_status": settlement.settlement_status, "remark": settlement.remark, } return response @router.post("", response_model=SettlementResponse, status_code=status.HTTP_201_CREATED) async def create_settlement(settlement: SettlementCreate, db: AsyncSession = Depends(get_async_session)): """ 创建新的佣金结算单 """ logger.info(f"创建佣金结算单: {settlement.settlement_no}") # 生成结算单ID query = select(func.count()).select_from(Settlement) result = await db.execute(query) count = result.scalar() settlement_id = f"STL{2024}{(count + 1):06d}" # 创建新结算单 new_settlement = Settlement( settlement_id=settlement_id, settlement_no=settlement.settlement_no, streamer_id=settlement.streamer_id, streamer_name=settlement.streamer_name, streamer_entity_type=settlement.streamer_entity_type, settlement_period=settlement.settlement_period, settlement_start_date=settlement.settlement_start_date, settlement_end_date=settlement.settlement_end_date, order_count=settlement.order_count, total_sales=settlement.total_sales, total_commission=settlement.total_commission, platform_service_fee=settlement.platform_service_fee, actual_settlement_amount=settlement.actual_settlement_amount, tax_withholding=settlement.tax_withholding, payment_method=settlement.payment_method, payment_account_no=settlement.payment_account_no, payment_account_name=settlement.payment_account_name, payment_time=settlement.payment_time, payment_status=settlement.payment_status, settlement_status=settlement.settlement_status, remark=settlement.remark, ) db.add(new_settlement) await db.commit() await db.refresh(new_settlement) # 转换为响应格式 response = { "id": new_settlement.id, "settlement_id": new_settlement.settlement_id, "settlement_no": new_settlement.settlement_no, "streamer_id": new_settlement.streamer_id, "streamer_name": new_settlement.streamer_name, "streamer_entity_type": new_settlement.streamer_entity_type, "settlement_period": new_settlement.settlement_period, "settlement_start_date": new_settlement.settlement_start_date.isoformat() if new_settlement.settlement_start_date else None, "settlement_end_date": new_settlement.settlement_end_date.isoformat() if new_settlement.settlement_end_date else None, "order_count": new_settlement.order_count, "total_sales": new_settlement.total_sales, "total_commission": new_settlement.total_commission, "platform_service_fee": new_settlement.platform_service_fee, "actual_settlement_amount": new_settlement.actual_settlement_amount, "tax_withholding": new_settlement.tax_withholding, "payment_method": new_settlement.payment_method, "payment_account_no": new_settlement.payment_account_no, "payment_account_name": new_settlement.payment_account_name, "payment_time": new_settlement.payment_time.isoformat() if new_settlement.payment_time else None, "payment_status": new_settlement.payment_status, "settlement_status": new_settlement.settlement_status, "remark": new_settlement.remark, } return response @router.put("/{settlement_id}", response_model=SettlementResponse) async def update_settlement( settlement_id: str, settlement_update: SettlementUpdate, db: AsyncSession = Depends(get_async_session), ): """ 更新佣金结算单 """ logger.info(f"更新佣金结算单: {settlement_id}") query = select(Settlement).where(Settlement.settlement_id == settlement_id) result = await db.execute(query) settlement = result.scalar_one_or_none() if not settlement: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"佣金结算单不存在: {settlement_id}", ) # 更新字段 update_data = settlement_update.model_dump(exclude_unset=True) for key, value in update_data.items(): if hasattr(settlement, key): setattr(settlement, key, value) await db.commit() await db.refresh(settlement) # 转换为响应格式 response = { "id": settlement.id, "settlement_id": settlement.settlement_id, "settlement_no": settlement.settlement_no, "streamer_id": settlement.streamer_id, "streamer_name": settlement.streamer_name, "streamer_entity_type": settlement.streamer_entity_type, "settlement_period": settlement.settlement_period, "settlement_start_date": settlement.settlement_start_date.isoformat() if settlement.settlement_start_date else None, "settlement_end_date": settlement.settlement_end_date.isoformat() if settlement.settlement_end_date else None, "order_count": settlement.order_count, "total_sales": settlement.total_sales, "total_commission": settlement.total_commission, "platform_service_fee": settlement.platform_service_fee, "actual_settlement_amount": settlement.actual_settlement_amount, "tax_withholding": settlement.tax_withholding, "payment_method": settlement.payment_method, "payment_account_no": settlement.payment_account_no, "payment_account_name": settlement.payment_account_name, "payment_time": settlement.payment_time.isoformat() if settlement.payment_time else None, "payment_status": settlement.payment_status, "settlement_status": settlement.settlement_status, "remark": settlement.remark, } return response @router.delete("/{settlement_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_settlement(settlement_id: str, db: AsyncSession = Depends(get_async_session)): """ 删除佣金结算单(软删除) """ logger.info(f"删除佣金结算单: {settlement_id}") query = select(Settlement).where(Settlement.settlement_id == settlement_id) result = await db.execute(query) settlement = result.scalar_one_or_none() if not settlement: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"佣金结算单不存在: {settlement_id}", ) # 软删除 - 设置为已取消状态 await db.delete(settlement) await db.commit() return None