feat: add document-types endpoint and date/user filters to list

- GET /api/document-types: returns {id, name, code} from
  leaudit_document_types, with optional ?ids=1,2,3 filter
- GET /api/documents/list: added userId, dateFrom, dateTo
  query params for filtering by uploading user and date range
This commit is contained in:
wren
2026-04-30 12:28:55 +08:00
parent b6d7f154ad
commit 8f307aecba
4 changed files with 87 additions and 3 deletions
@@ -1,11 +1,13 @@
"""文档控制器。"""
from fastapi import File, Form, UploadFile
from typing import Any
from fastapi import File, Form, Query, UploadFile
from fastapi_common.fastapi_common_web.controller import BaseController
from fastapi_common.fastapi_common_web.domain.responses import Result
from fastapi_modules.fastapi_leaudit.domian.vo.documentVo import DocumentListPageVO, DocumentUploadVO
from fastapi_modules.fastapi_leaudit.domian.vo.documentVo import DocumentListPageVO, DocumentTypeItemVO, DocumentUploadVO
from fastapi_modules.fastapi_leaudit.services import IDocumentService
from fastapi_modules.fastapi_leaudit.services.impl.documentServiceImpl import DocumentServiceImpl
@@ -53,6 +55,9 @@ class DocumentController(BaseController):
region: str | None = None,
processingStatus: str | None = None,
resultStatus: str | None = None,
userId: int | None = Query(None, description="按用户ID过滤"),
dateFrom: str | None = Query(None, description="起始日期 (YYYY-MM-DD)"),
dateTo: str | None = Query(None, description="结束日期 (YYYY-MM-DD)"),
):
"""获取文档列表(仅返回最新版本,附历史版本摘要)。"""
Data = await self.DocumentService.ListDocuments(
@@ -63,5 +68,19 @@ class DocumentController(BaseController):
Region=region,
ProcessingStatus=processingStatus,
ResultStatus=resultStatus,
UserId=userId,
DateFrom=dateFrom,
DateTo=dateTo,
)
return Result.success(data=Data)
@self.router.get("/document-types", response_model=Result[list[DocumentTypeItemVO]])
async def ListDocumentTypes(
ids: str | None = Query(None, description="逗号分隔的ID列表,不传则返回全部"),
):
"""获取文档类型列表。"""
idList: list[int] | None = None
if ids:
idList = [int(x.strip()) for x in ids.split(",") if x.strip().isdigit()]
Data = await self.DocumentService.ListDocumentTypes(Ids=idList)
return Result.success(data=Data)
@@ -74,6 +74,14 @@ class DocumentListItemVO(BaseModel):
historyVersions: list[DocumentHistoryVersionVO] = Field(default_factory=list, description="历史版本摘要")
class DocumentTypeItemVO(BaseModel):
"""文档类型列表项。"""
id: int = Field(..., description="类型ID")
name: str = Field(..., description="类型名称")
code: str = Field(..., description="类型编码")
class DocumentListPageVO(BaseModel):
"""文档列表分页结果。"""
@@ -2,7 +2,7 @@
from abc import ABC, abstractmethod
from fastapi_modules.fastapi_leaudit.domian.vo.documentVo import DocumentListPageVO, DocumentUploadVO
from fastapi_modules.fastapi_leaudit.domian.vo.documentVo import DocumentListPageVO, DocumentTypeItemVO, DocumentUploadVO
class IDocumentService(ABC):
@@ -35,6 +35,14 @@ class IDocumentService(ABC):
Region: str | None = None,
ProcessingStatus: str | None = None,
ResultStatus: str | None = None,
UserId: int | None = None,
DateFrom: str | None = None,
DateTo: str | None = None,
) -> DocumentListPageVO:
"""获取文档列表(仅最新版本,附历史版本摘要)。"""
...
@abstractmethod
async def ListDocumentTypes(self, Ids: list[int] | None = None) -> list[DocumentTypeItemVO]:
"""获取文档类型列表。"""
...
@@ -22,6 +22,7 @@ from fastapi_modules.fastapi_leaudit.domian.vo.documentVo import (
DocumentHistoryVersionVO,
DocumentListItemVO,
DocumentListPageVO,
DocumentTypeItemVO,
DocumentUploadVO,
)
from fastapi_modules.fastapi_leaudit.models import LeauditDocument, LeauditDocumentFile
@@ -254,6 +255,9 @@ class DocumentServiceImpl(IDocumentService):
Region: str | None = None,
ProcessingStatus: str | None = None,
ResultStatus: str | None = None,
UserId: int | None = None,
DateFrom: str | None = None,
DateTo: str | None = None,
) -> DocumentListPageVO:
"""获取文档列表(仅最新版本,附历史版本摘要)。"""
page = max(1, int(Page))
@@ -278,6 +282,15 @@ class DocumentServiceImpl(IDocumentService):
if ResultStatus:
filters.append("ar.result_status = :result_status")
params["result_status"] = ResultStatus.strip()
if UserId is not None:
filters.append("f.created_by = :user_id")
params["user_id"] = UserId
if DateFrom:
filters.append("d.created_at >= :date_from")
params["date_from"] = DateFrom.strip()
if DateTo:
filters.append("d.created_at < (CAST(:date_to AS date) + INTERVAL '1 day')")
params["date_to"] = DateTo.strip()
where_clause = " AND ".join(filters)
@@ -443,6 +456,42 @@ class DocumentServiceImpl(IDocumentService):
)
async def ListDocumentTypes(self, Ids: list[int] | None = None) -> list[DocumentTypeItemVO]:
"""获取文档类型列表。"""
async with GetAsyncSession() as Session:
if Ids:
rows = (
await Session.execute(
text(
"""
SELECT id, name, code
FROM leaudit_document_types
WHERE deleted_at IS NULL AND id = ANY(:ids)
ORDER BY sort_order ASC, id ASC
"""
),
{"ids": Ids},
)
).mappings().all()
else:
rows = (
await Session.execute(
text(
"""
SELECT id, name, code
FROM leaudit_document_types
WHERE deleted_at IS NULL
ORDER BY sort_order ASC, id ASC
"""
)
)
).mappings().all()
return [
DocumentTypeItemVO(id=int(r["id"]), name=str(r["name"] or ""), code=str(r["code"] or ""))
for r in rows
]
async def _find_latest_version_candidate(
session,
*,