""" 税务申报表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.tax_declaration import TaxDeclaration from app.schemas.tax import ( TaxDeclarationCreate, TaxDeclarationUpdate, TaxDeclarationResponse, TaxDeclarationListResponse, ) router = APIRouter() @router.get("", response_model=TaxDeclarationListResponse) async def list_tax_declarations( page: int = Query(1, ge=1, description="页码"), size: int = Query(10, ge=1, le=100, description="每页数量"), vat_declaration_id: str = Query(None, description="增值税申报ID"), taxpayer_name: str = Query(None, description="纳税人名称"), taxpayer_id: str = Query(None, description="纳税人识别号"), declaration_status: str = Query(None, description="申报状态"), db: AsyncSession = Depends(get_async_session), ): """ 获取税务申报表列表(分页查询) """ logger.info(f"获取税务申报表列表: page={page}, size={size}") # 构建查询 query = select(TaxDeclaration) # 添加过滤条件 conditions = [] if vat_declaration_id: conditions.append(TaxDeclaration.vat_declaration_id.ilike(f"%{vat_declaration_id}%")) if taxpayer_name: conditions.append(TaxDeclaration.taxpayer_name.ilike(f"%{taxpayer_name}%")) if taxpayer_id: conditions.append(TaxDeclaration.taxpayer_id == taxpayer_id) if declaration_status: conditions.append(TaxDeclaration.declaration_status == declaration_status) if conditions: query = query.where(and_(*conditions)) # 获取总数 count_query = select(func.count()).select_from(TaxDeclaration) 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 tax in records: response_records.append({ "id": tax.id, "vat_declaration_id": tax.vat_declaration_id, "taxpayer_name": tax.taxpayer_name, "taxpayer_id": tax.taxpayer_id, "tax_period": tax.tax_period, "declaration_date": tax.declaration_date.isoformat() if tax.declaration_date else None, "tax_authority_code": tax.tax_authority_code, "tax_authority_name": tax.tax_authority_name, "taxpayer_type": tax.taxpayer_type, "tax_rate": tax.tax_rate, "sales_revenue": tax.sales_revenue, "sales_revenue_taxable": tax.sales_revenue_taxable, "output_tax": tax.output_tax, "input_tax": tax.input_tax, "input_tax_deductible": tax.input_tax_deductible, "tax_payable": tax.tax_payable, "tax_to_pay": tax.tax_to_pay, "refund_amount": tax.refund_amount, "declaration_status": tax.declaration_status, "is_reconciled": tax.is_reconciled, }) return TaxDeclarationListResponse( records=response_records, total=total, page=page, size=size, ) @router.get("/{vat_declaration_id}", response_model=TaxDeclarationResponse) async def get_tax_declaration(vat_declaration_id: str, db: AsyncSession = Depends(get_async_session)): """ 根据ID获取税务申报表详细信息 """ logger.info(f"获取税务申报表详情: {vat_declaration_id}") query = select(TaxDeclaration).where(TaxDeclaration.vat_declaration_id == vat_declaration_id) result = await db.execute(query) tax = result.scalar_one_or_none() if not tax: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"税务申报表不存在: {vat_declaration_id}", ) # 转换为响应格式 response = { "id": tax.id, "vat_declaration_id": tax.vat_declaration_id, "taxpayer_name": tax.taxpayer_name, "taxpayer_id": tax.taxpayer_id, "tax_period": tax.tax_period, "declaration_date": tax.declaration_date.isoformat() if tax.declaration_date else None, "tax_authority_code": tax.tax_authority_code, "tax_authority_name": tax.tax_authority_name, "taxpayer_type": tax.taxpayer_type, "tax_rate": tax.tax_rate, "sales_revenue": tax.sales_revenue, "sales_revenue_taxable": tax.sales_revenue_taxable, "output_tax": tax.output_tax, "input_tax": tax.input_tax, "input_tax_deductible": tax.input_tax_deductible, "tax_payable": tax.tax_payable, "tax_to_pay": tax.tax_to_pay, "refund_amount": tax.refund_amount, "declaration_status": tax.declaration_status, "is_reconciled": tax.is_reconciled, } return response @router.post("", response_model=TaxDeclarationResponse, status_code=status.HTTP_201_CREATED) async def create_tax_declaration(tax: TaxDeclarationCreate, db: AsyncSession = Depends(get_async_session)): """ 创建新的税务申报表 """ logger.info(f"创建税务申报表: {tax.taxpayer_name}") # 生成申报ID query = select(func.count()).select_from(TaxDeclaration) result = await db.execute(query) count = result.scalar() vat_declaration_id = f"TAX{2024}{(count + 1):06d}" # 创建新申报 new_tax = TaxDeclaration( vat_declaration_id=vat_declaration_id, taxpayer_name=tax.taxpayer_name, taxpayer_id=tax.taxpayer_id, tax_period=tax.tax_period, declaration_date=tax.declaration_date, tax_authority_code=tax.tax_authority_code, tax_authority_name=tax.tax_authority_name, taxpayer_type=tax.taxpayer_type, tax_rate=tax.tax_rate, sales_revenue=tax.sales_revenue, sales_revenue_taxable=tax.sales_revenue_taxable, output_tax=tax.output_tax, input_tax=tax.input_tax, input_tax_deductible=tax.input_tax_deductible, tax_payable=tax.tax_payable, tax_to_pay=tax.tax_to_pay, refund_amount=tax.refund_amount, declaration_status=tax.declaration_status, is_reconciled=tax.is_reconciled, ) db.add(new_tax) await db.commit() await db.refresh(new_tax) # 转换为响应格式 response = { "id": new_tax.id, "vat_declaration_id": new_tax.vat_declaration_id, "taxpayer_name": new_tax.taxpayer_name, "taxpayer_id": new_tax.taxpayer_id, "tax_period": new_tax.tax_period, "declaration_date": new_tax.declaration_date.isoformat() if new_tax.declaration_date else None, "tax_authority_code": new_tax.tax_authority_code, "tax_authority_name": new_tax.tax_authority_name, "taxpayer_type": new_tax.taxpayer_type, "tax_rate": new_tax.tax_rate, "sales_revenue": new_tax.sales_revenue, "sales_revenue_taxable": new_tax.sales_revenue_taxable, "output_tax": new_tax.output_tax, "input_tax": new_tax.input_tax, "input_tax_deductible": new_tax.input_tax_deductible, "tax_payable": new_tax.tax_payable, "tax_to_pay": new_tax.tax_to_pay, "refund_amount": new_tax.refund_amount, "declaration_status": new_tax.declaration_status, "is_reconciled": new_tax.is_reconciled, } return response @router.put("/{vat_declaration_id}", response_model=TaxDeclarationResponse) async def update_tax_declaration( vat_declaration_id: str, tax_update: TaxDeclarationUpdate, db: AsyncSession = Depends(get_async_session), ): """ 更新税务申报表 """ logger.info(f"更新税务申报表: {vat_declaration_id}") query = select(TaxDeclaration).where(TaxDeclaration.vat_declaration_id == vat_declaration_id) result = await db.execute(query) tax = result.scalar_one_or_none() if not tax: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"税务申报表不存在: {vat_declaration_id}", ) # 更新字段 update_data = tax_update.model_dump(exclude_unset=True) for key, value in update_data.items(): if hasattr(tax, key): setattr(tax, key, value) await db.commit() await db.refresh(tax) # 转换为响应格式 response = { "id": tax.id, "vat_declaration_id": tax.vat_declaration_id, "taxpayer_name": tax.taxpayer_name, "taxpayer_id": tax.taxpayer_id, "tax_period": tax.tax_period, "declaration_date": tax.declaration_date.isoformat() if tax.declaration_date else None, "tax_authority_code": tax.tax_authority_code, "tax_authority_name": tax.tax_authority_name, "taxpayer_type": tax.taxpayer_type, "tax_rate": tax.tax_rate, "sales_revenue": tax.sales_revenue, "sales_revenue_taxable": tax.sales_revenue_taxable, "output_tax": tax.output_tax, "input_tax": tax.input_tax, "input_tax_deductible": tax.input_tax_deductible, "tax_payable": tax.tax_payable, "tax_to_pay": tax.tax_to_pay, "refund_amount": tax.refund_amount, "declaration_status": tax.declaration_status, "is_reconciled": tax.is_reconciled, } return response @router.delete("/{vat_declaration_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_tax_declaration(vat_declaration_id: str, db: AsyncSession = Depends(get_async_session)): """ 删除税务申报表(软删除) """ logger.info(f"删除税务申报表: {vat_declaration_id}") query = select(TaxDeclaration).where(TaxDeclaration.vat_declaration_id == vat_declaration_id) result = await db.execute(query) tax = result.scalar_one_or_none() if not tax: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"税务申报表不存在: {vat_declaration_id}", ) # 软删除 - 设置为草稿状态 tax.declaration_status = "rejected" await db.commit() return None