293 lines
10 KiB
Python
293 lines
10 KiB
Python
"""
|
|
税务申报表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
|