Files
X-Financial/server/tests/test_document_numbering.py
caoxiaozhu 0e861d8fa6 feat: 增强风险规则生成引擎与预算中心页面
后端拆分风险规则生成为解释器、语义分析、本体对齐等子模块,
优化模板执行和流程图生成,完善员工种子数据和导入逻辑,增强
报销单权限策略和草稿持久化,前端新增预算中心视图和趋势图
组件,重构审计页面和风险规则测试对话框交互,完善文档中心
和报销创建页面细节,补充单元测试覆盖。
2026-05-26 09:15:14 +08:00

95 lines
2.9 KiB
Python

from __future__ import annotations
from datetime import UTC, datetime
from decimal import Decimal
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.pool import StaticPool
from app.db.base import Base
from app.models.financial_record import ExpenseClaim
from app.services.document_numbering import (
build_document_number,
generate_unique_expense_claim_no,
is_application_claim_no,
)
def build_session() -> Session:
engine = create_engine(
"sqlite+pysqlite:///:memory:",
connect_args={"check_same_thread": False},
poolclass=StaticPool,
)
Base.metadata.create_all(bind=engine)
factory = sessionmaker(bind=engine, autoflush=False, autocommit=False)
return factory()
def test_build_document_number_uses_kind_prefix_timestamp_and_token() -> None:
timestamp = datetime(2026, 5, 25, 10, 30, 45, tzinfo=UTC)
assert (
build_document_number("application", timestamp=timestamp, token="ABCDEFGH")
== "AP-20260525103045-ABCDEFGH"
)
assert (
build_document_number("reimbursement", timestamp=timestamp, token="ABCDEFGH")
== "RE-20260525103045-ABCDEFGH"
)
assert (
build_document_number("audit", timestamp=timestamp, token="ABCDEFGH")
== "AD-20260525103045-ABCDEFGH"
)
def test_build_document_number_rejects_ambiguous_token_chars() -> None:
timestamp = datetime(2026, 5, 25, 10, 30, 45, tzinfo=UTC)
with pytest.raises(ValueError):
build_document_number("application", timestamp=timestamp, token="ABCDEF10")
def test_generate_unique_expense_claim_no_retries_existing_candidate() -> None:
timestamp = datetime(2026, 5, 25, 10, 30, 45, tzinfo=UTC)
with build_session() as db:
db.add(
ExpenseClaim(
claim_no="RE-20260525103045-ABCDEFGH",
employee_name="张三",
department_name="市场部",
project_code=None,
expense_type="transport",
reason="交通报销",
location="深圳",
amount=Decimal("10.00"),
currency="CNY",
invoice_count=1,
occurred_at=timestamp,
status="draft",
approval_stage="待提交",
risk_flags_json=[],
)
)
db.commit()
tokens = iter(["ABCDEFGH", "HGFEDCBA"])
assert (
generate_unique_expense_claim_no(
db,
"reimbursement",
timestamp=timestamp,
token_factory=lambda: next(tokens),
)
== "RE-20260525103045-HGFEDCBA"
)
def test_is_application_claim_no_supports_new_and_legacy_prefixes() -> None:
assert is_application_claim_no("AP-20260525103045-ABCDEFGH")
assert is_application_claim_no("APP-20260525-ABC123")
assert not is_application_claim_no("RE-20260525103045-ABCDEFGH")