invoice.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import mimetypes
  2. from typing import List, Optional
  3. from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile, status
  4. from sqlalchemy.orm import Session
  5. from app.core.bx_auth import BxUserContext, get_bx_current_user
  6. from app.core.database import get_db
  7. from app.schemas.bx.common import ApiResponse, PagedData
  8. from app.schemas.bx.invoice import InvoiceOut, LedgerOut, WalletSummaryOut
  9. from app.services.bx.invoice import InvoiceService
  10. router = APIRouter(tags=["发票夹"])
  11. @router.get("/invoice-wallets/mine/summary", response_model=ApiResponse[WalletSummaryOut])
  12. def get_mine_wallet_summary(
  13. db: Session = Depends(get_db),
  14. user: BxUserContext = Depends(get_bx_current_user),
  15. ):
  16. data = InvoiceService.get_mine_summary(db, user=user)
  17. return ApiResponse(data=WalletSummaryOut.model_validate(data))
  18. @router.get("/invoice-wallets", response_model=ApiResponse[PagedData[WalletSummaryOut]])
  19. def list_invoice_wallets(
  20. page: int = 1,
  21. pageSize: int = 10,
  22. keyword: str = "",
  23. db: Session = Depends(get_db),
  24. user: BxUserContext = Depends(get_bx_current_user),
  25. ):
  26. rows, total = InvoiceService.list_wallets(
  27. db, user=user, page=page, page_size=pageSize, keyword=keyword
  28. )
  29. out_rows = [WalletSummaryOut.model_validate(InvoiceService._summary_to_dict(r)) for r in rows]
  30. return ApiResponse(data=PagedData(rows=out_rows, total=total, page=page, page_size=pageSize))
  31. @router.get("/invoices", response_model=ApiResponse[PagedData[InvoiceOut]])
  32. def list_invoices(
  33. page: int = 1,
  34. pageSize: int = 10,
  35. userId: Optional[str] = None,
  36. db: Session = Depends(get_db),
  37. user: BxUserContext = Depends(get_bx_current_user),
  38. ):
  39. tenant_no = InvoiceService._tenant_no(db, user)
  40. rows, total = InvoiceService.list_invoices(
  41. db, user=user, owner_user_id=userId, page=page, page_size=pageSize
  42. )
  43. out_rows = InvoiceService.out_rows_with_attachments(db, tenant_no, list(rows))
  44. return ApiResponse(
  45. data=PagedData(
  46. rows=[InvoiceOut.model_validate(r) for r in out_rows],
  47. total=total,
  48. page=page,
  49. page_size=pageSize,
  50. )
  51. )
  52. @router.post("/invoices", response_model=ApiResponse[InvoiceOut])
  53. def create_invoice(
  54. file: UploadFile = File(...),
  55. amount: float = Form(...),
  56. remark: str = Form(""),
  57. targetUserId: Optional[str] = Form(None),
  58. db: Session = Depends(get_db),
  59. user: BxUserContext = Depends(get_bx_current_user),
  60. ):
  61. if not file or not file.filename:
  62. raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="请选择文件")
  63. file_data = file.file.read()
  64. content_type = (
  65. file.content_type
  66. or mimetypes.guess_type(file.filename or "")[0]
  67. or "application/octet-stream"
  68. )
  69. try:
  70. invoice = InvoiceService.create(
  71. db,
  72. user=user,
  73. amount=amount,
  74. file_data=file_data,
  75. filename=file.filename or "unknown",
  76. content_type=content_type,
  77. remark=remark,
  78. target_user_id=targetUserId,
  79. )
  80. db.commit()
  81. db.refresh(invoice)
  82. except HTTPException:
  83. db.rollback()
  84. raise
  85. except Exception as exc:
  86. db.rollback()
  87. raise HTTPException(
  88. status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="上传发票失败"
  89. ) from exc
  90. tenant_no = InvoiceService._tenant_no(db, user)
  91. out = InvoiceService.out_rows_with_attachments(db, tenant_no, [invoice])[0]
  92. return ApiResponse(data=InvoiceOut.model_validate(out))
  93. @router.delete("/invoices/{invoice_id}", response_model=ApiResponse[bool])
  94. def delete_invoice(
  95. invoice_id: str,
  96. db: Session = Depends(get_db),
  97. user: BxUserContext = Depends(get_bx_current_user),
  98. ):
  99. try:
  100. success = InvoiceService.delete(db, user=user, invoice_id=invoice_id)
  101. db.commit()
  102. except HTTPException:
  103. db.rollback()
  104. raise
  105. return ApiResponse(data=success)
  106. @router.get("/invoice-ledgers", response_model=ApiResponse[List[LedgerOut]])
  107. def list_invoice_ledgers(
  108. userId: Optional[str] = None,
  109. db: Session = Depends(get_db),
  110. user: BxUserContext = Depends(get_bx_current_user),
  111. ):
  112. rows = InvoiceService.list_ledgers(db, user=user, owner_user_id=userId)
  113. return ApiResponse(data=[LedgerOut.model_validate(r) for r in rows])