diff --git a/fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py b/fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py index 9e79fa5..5ce2d16 100644 --- a/fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py +++ b/fastapi_modules/fastapi_leaudit/services/impl/homeServiceImpl.py @@ -417,6 +417,27 @@ class HomeServiceImpl(IHomeService): except ValueError: return None + def normalized_document_status(Document: Any) -> tuple[int, int, int, str, str]: + audit_status = int(getattr(Document, "auditStatus", 0) or 0) + passed_count = int(getattr(Document, "passedCount", 0) or 0) + failed_count = int(getattr(Document, "failedCount", 0) or 0) + run_status = str(getattr(Document, "runStatus", "") or "").strip().lower() + result_status = str(getattr(Document, "resultStatus", "") or "").strip().lower() + return audit_status, passed_count, failed_count, run_status, result_status + + def is_reviewed_document(Document: Any) -> bool: + audit_status, passed_count, failed_count, run_status, result_status = normalized_document_status(Document) + if audit_status in {-1, 1}: + return True + if passed_count > 0 or failed_count > 0: + return True + if result_status in {"pass", "fail", "partial", "review", "error"}: + return True + return run_status == "completed" + + def is_pending_document(Document: Any) -> bool: + return not is_reviewed_document(Document) + def in_range(Document: Any, DateFrom: date, DateTo: date) -> bool: current_date = document_date(Document) return current_date is not None and DateFrom <= current_date <= DateTo @@ -427,15 +448,15 @@ class HomeServiceImpl(IHomeService): previous_month_documents = [ document for document in documents if in_range(document, previous_month_start, previous_month_end) ] - current_reviewed_documents = [document for document in current_month_documents if int(document.auditStatus or 0) == 1] - previous_reviewed_documents = [document for document in previous_month_documents if int(document.auditStatus or 0) == 1] + current_reviewed_documents = [document for document in current_month_documents if is_reviewed_document(document)] + previous_reviewed_documents = [document for document in previous_month_documents if is_reviewed_document(document)] current_pass_rate = pass_rate(current_reviewed_documents) previous_pass_rate = pass_rate(previous_reviewed_documents) current_issue_count = issue_count(current_reviewed_documents) previous_issue_count = issue_count(previous_reviewed_documents) return HomeDashboardStatisticsVO( - todayPendingFiles=len([document for document in today_documents if int(document.auditStatus or 0) != 1]), + todayPendingFiles=len([document for document in today_documents if is_pending_document(document)]), monthlyReviewedFiles=len(current_reviewed_documents), monthlyReviewGrowth=growth(len(current_reviewed_documents), len(previous_reviewed_documents)), monthlyPassRate=current_pass_rate, diff --git a/legal-platform-frontend b/legal-platform-frontend index 76795e2..c4f02f5 160000 --- a/legal-platform-frontend +++ b/legal-platform-frontend @@ -1 +1 @@ -Subproject commit 76795e2f1543627965ec5033353a93281a6017d1 +Subproject commit c4f02f545ad73909c8ce3fd80794177f8f288bfc diff --git a/tests/test_home_dashboard_statistics.py b/tests/test_home_dashboard_statistics.py index 1aaece5..40e1115 100644 --- a/tests/test_home_dashboard_statistics.py +++ b/tests/test_home_dashboard_statistics.py @@ -6,10 +6,24 @@ from fastapi_modules.fastapi_leaudit.services.impl.homeServiceImpl import HomeSe class _FakeDocument: - def __init__(self, *, audit_status: int, failed_count: int = 0, updated_at: str = "2026-05-23T10:00:00") -> None: + def __init__( + self, + *, + audit_status: int, + failed_count: int = 0, + passed_count: int | None = None, + updated_at: str = "2026-05-23T10:00:00", + processing_status: str | None = None, + run_status: str | None = None, + result_status: str | None = None, + ) -> None: self.auditStatus = audit_status self.failedCount = failed_count + self.passedCount = passed_count self.updatedAt = updated_at + self.processingStatus = processing_status or ("running" if audit_status == 2 else "waiting" if audit_status == 0 else "completed") + self.runStatus = run_status or ("running" if audit_status == 2 else "pending" if audit_status == 0 else "completed") + self.resultStatus = result_status class _FakePage: @@ -47,6 +61,49 @@ class _FakeDocumentService: return _FakePage(documents=[], total_pages=2) +class _FakeFailedReviewDocumentService: + def __init__(self) -> None: + self.calls = [] + + async def ListDocuments(self, **kwargs): + self.calls.append(kwargs) + return _FakePage( + documents=[ + _FakeDocument( + audit_status=0, + passed_count=5, + failed_count=0, + updated_at="2026-05-21T09:00:00", + run_status="completed", + result_status="pass", + ), + _FakeDocument( + audit_status=0, + failed_count=3, + updated_at="2026-05-21T10:00:00", + run_status="completed", + result_status="fail", + ), + _FakeDocument( + audit_status=0, + failed_count=0, + updated_at="2026-05-21T11:00:00", + processing_status="waiting", + run_status="pending", + result_status=None, + ), + _FakeDocument( + audit_status=0, + failed_count=1, + updated_at="2026-04-18T10:00:00", + run_status="completed", + result_status="fail", + ), + ], + total_pages=1, + ) + + @pytest.mark.asyncio async def test_home_dashboard_statistics_uses_entry_scope_and_all_pages(): """首页统计按入口模块与文档类型过滤,并拉取全量分页后计算。""" @@ -71,3 +128,17 @@ async def test_home_dashboard_statistics_uses_entry_scope_and_all_pages(): assert [call["Page"] for call in document_service.calls] == [1, 2] assert all("DateFrom" not in call for call in document_service.calls) assert all("DateTo" not in call for call in document_service.calls) + + +@pytest.mark.asyncio +async def test_home_dashboard_statistics_counts_failed_reviews_as_reviewed(): + """首页已审核统计应包含不通过但已评查完成的文件。""" + document_service = _FakeFailedReviewDocumentService() + service = HomeServiceImpl(DocumentService=document_service) + + result = await service.GetDashboardStatistics(UserId=7, Today="2026-05-21") + + assert result.todayPendingFiles == 1 + assert result.monthlyReviewedFiles == 2 + assert result.monthlyPassRate == 50 + assert result.issuesDetected == 3