guzhi/app/api/v1/invoice/invoice.py
邹方成 cc352d3184 feat: 重构后端服务并添加新功能
refactor: 优化API路由和响应模型
feat(admin): 添加App用户管理接口
feat(sms): 实现阿里云短信服务集成
feat(email): 添加SMTP邮件发送功能
feat(upload): 支持文件上传接口
feat(rate-limiter): 实现手机号限流器
fix: 修复计算步骤入库问题
docs: 更新API文档和测试计划
chore: 更新依赖和配置
2025-11-19 19:36:03 +08:00

154 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from fastapi import APIRouter, Query
from typing import Optional
from app.schemas.base import Success, SuccessExtra, BasicResponse, PageResponse, MessageOut
from app.schemas.invoice import (
InvoiceCreate,
InvoiceUpdate,
UpdateStatus,
UpdateType,
InvoiceHeaderCreate,
PaymentReceiptCreate,
InvoiceOut,
InvoiceList,
InvoiceHeaderOut,
PaymentReceiptOut,
)
from app.controllers.invoice import invoice_controller
invoice_router = APIRouter(tags=["发票管理"])
@invoice_router.get("/list", summary="获取发票列表", response_model=PageResponse[InvoiceOut])
async def list_invoices(
phone: Optional[str] = Query(None),
company_name: Optional[str] = Query(None),
tax_number: Optional[str] = Query(None),
status: Optional[str] = Query(None),
ticket_type: Optional[str] = Query(None),
invoice_type: Optional[str] = Query(None),
page: int = Query(1, ge=1),
page_size: int = Query(10, ge=1, le=100),
):
"""
发票列表查询
参数支持按手机号、公司名称、税号、状态、发票类型进行筛选
返回分页结构
"""
result = await invoice_controller.list(
page=page,
page_size=page_size,
phone=phone,
company_name=company_name,
tax_number=tax_number,
status=status,
ticket_type=ticket_type,
invoice_type=invoice_type,
)
return SuccessExtra(
data=result.items, total=result.total, page=result.page, page_size=result.page_size, msg="获取成功"
)
@invoice_router.get("/detail", summary="发票详情", response_model=BasicResponse[InvoiceOut])
async def invoice_detail(id: int = Query(...)):
"""
根据ID获取发票详情
"""
out = await invoice_controller.get_out(id)
if not out:
return Success(data={}, msg="未找到")
return Success(data=out, msg="获取成功")
@invoice_router.post("/create", summary="创建发票", response_model=BasicResponse[InvoiceOut])
async def create_invoice(data: InvoiceCreate):
"""
创建发票记录
"""
inv = await invoice_controller.create(data)
out = await invoice_controller.get_out(inv.id)
return Success(data=out, msg="创建成功")
@invoice_router.post("/update", summary="更新发票", response_model=BasicResponse[InvoiceOut])
async def update_invoice(data: InvoiceUpdate, id: int = Query(...)):
"""
更新发票记录
"""
updated = await invoice_controller.update(id, data)
out = await invoice_controller.get_out(id) if updated else None
return Success(data=out or {}, msg="更新成功" if updated else "未找到")
@invoice_router.delete("/delete", summary="删除发票", response_model=BasicResponse[MessageOut])
async def delete_invoice(id: int = Query(...)):
"""
删除发票记录
"""
try:
await invoice_controller.remove(id)
ok = True
except Exception:
ok = False
return Success(data={"deleted": ok}, msg="删除成功" if ok else "未找到")
@invoice_router.post("/update-status", summary="更新发票状态", response_model=BasicResponse[InvoiceOut])
async def update_invoice_status(data: UpdateStatus):
"""
更新发票状态pending|invoiced|rejected|refunded
"""
out = await invoice_controller.update_status(data)
return Success(data=out or {}, msg="更新成功" if out else "未找到")
@invoice_router.post("/{id}/receipt", summary="上传付款凭证", response_model=BasicResponse[PaymentReceiptOut])
async def upload_payment_receipt(id: int, data: PaymentReceiptCreate):
"""
上传对公转账付款凭证
"""
receipt = await invoice_controller.create_receipt(id, data)
return Success(data=receipt, msg="上传成功")
@invoice_router.get("/headers", summary="发票抬头列表", response_model=BasicResponse[list[InvoiceHeaderOut]])
async def get_invoice_headers(app_user_id: Optional[int] = Query(None)):
"""
获取发票抬头列表,可按 AppUser 过滤
"""
headers = await invoice_controller.get_headers(user_id=app_user_id)
return Success(data=headers, msg="获取成功")
@invoice_router.get("/headers/{id}", summary="发票抬头详情", response_model=BasicResponse[InvoiceHeaderOut])
async def get_invoice_header_by_id(id: int):
"""
获取发票抬头详情
"""
header = await invoice_controller.get_header_by_id(id)
return Success(data=header or {}, msg="获取成功" if header else "未找到")
@invoice_router.post("/headers", summary="新增发票抬头", response_model=BasicResponse[InvoiceHeaderOut])
async def create_invoice_header(data: InvoiceHeaderCreate, app_user_id: Optional[int] = Query(None)):
"""
新增发票抬头
"""
header = await invoice_controller.create_header(user_id=app_user_id, data=data)
return Success(data=header, msg="创建成功")
@invoice_router.put("/{id}/type", summary="更新发票类型", response_model=BasicResponse[InvoiceOut])
async def update_invoice_type(id: int, data: UpdateType):
"""
更新发票的电子/纸质与专票/普票类型
"""
out = await invoice_controller.update_type(id, data)
return Success(data=out or {}, msg="更新成功" if out else "未找到")
# 对公转账记录接口在 transactions 路由中统一暴露