Files
X-Financial/server/tests/test_finance_report_task.py

100 lines
3.4 KiB
Python
Raw Normal View History

from __future__ import annotations
from datetime import UTC, datetime, timedelta
from decimal import Decimal
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.pool import StaticPool
from app.core.config import get_settings
from app.db.base import Base
from app.models.agent_run import AgentRun
from app.models.financial_record import ExpenseClaim
from app.models.risk_observation import RiskObservation
from app.services.digital_employee_finance_report_task import (
FINANCE_REPORT_TASK_TYPE,
DigitalEmployeeFinanceReportTaskService,
)
def build_session() -> Session:
engine = create_engine(
"sqlite+pysqlite:///:memory:",
connect_args={"check_same_thread": False},
poolclass=StaticPool,
)
Base.metadata.create_all(bind=engine)
session_factory = sessionmaker(bind=engine, autoflush=False, autocommit=False)
return session_factory()
def test_finance_report_task_generates_pdf_and_agent_record(monkeypatch, tmp_path) -> None:
monkeypatch.setenv("STORAGE_ROOT_DIR", str(tmp_path))
get_settings.cache_clear()
now = datetime.now(UTC)
with build_session() as db:
db.add(
ExpenseClaim(
claim_no="RE-REPORT-001",
employee_name="林嘉宁",
department_name="市场部",
expense_type="travel",
reason="客户拜访",
location="上海",
amount=Decimal("3600.00"),
invoice_count=2,
occurred_at=now - timedelta(days=2),
submitted_at=now - timedelta(days=2),
status="paid",
approval_stage="已付款",
risk_flags_json=[],
hermes_risk_flag=False,
created_at=now - timedelta(days=2),
updated_at=now - timedelta(days=1),
)
)
db.add(
RiskObservation(
observation_key="risk-report-001",
subject_type="expense_claim",
subject_key="RE-REPORT-001",
subject_label="RE-REPORT-001",
claim_no="RE-REPORT-001",
risk_type="policy",
risk_signal="amount_outlier",
title="金额异常",
risk_level="high",
status="pending_review",
created_at=now - timedelta(days=1),
updated_at=now - timedelta(days=1),
)
)
db.commit()
result = DigitalEmployeeFinanceReportTaskService(db).generate_report(
report_type="weekly",
send_email=True,
dry_run_email=True,
)
pdf_path = tmp_path / result["pdf"]["storage_key"]
html_path = pdf_path.with_name("report.html")
runs = [
run
for run in db.query(AgentRun).filter(AgentRun.agent == "hermes").all()
if (run.route_json or {}).get("task_type") == FINANCE_REPORT_TASK_TYPE
]
assert pdf_path.exists()
assert pdf_path.read_bytes().startswith(b"%PDF")
assert html_path.exists()
assert result["delivery"]["status"] in {"dry_run", "pending_configuration"}
assert result["summary"]["reimbursement_count"] >= 1
assert runs
assert runs[0].status == "succeeded"
assert runs[0].route_json["report_delivery"]["pdf"]["storage_key"].endswith("report.pdf")
get_settings.cache_clear()