feat(platform): close AI expense value loop

Add tenant-safe value, telemetry, connector, commercial, and production-readiness foundations.
This commit is contained in:
caoxiaozhu
2026-07-17 14:14:08 +08:00
parent 242d68c36f
commit 787bc3a481
507 changed files with 82072 additions and 6344 deletions

View File

@@ -25,6 +25,7 @@ from app.services.expense_claim_workflow_constants import (
DIRECT_MANAGER_APPROVAL_STAGE,
)
from app.services.expense_claims import ExpenseClaimService
from app.services.tenant_registry import TenantRegistryService
def build_session() -> Session:
@@ -316,12 +317,15 @@ def test_submit_blocks_fixable_pre_review_before_budget_and_submission_event(
).all()
)
assert len(pre_review_events) == 1
assert db.scalar(
select(BusinessEvent).where(
BusinessEvent.aggregate_id == claim.id,
BusinessEvent.event_type == "claim_submitted",
assert (
db.scalar(
select(BusinessEvent).where(
BusinessEvent.aggregate_id == claim.id,
BusinessEvent.event_type == "claim_submitted",
)
)
) is None
is None
)
assert db.scalar(select(BudgetReservation)) is None
assert db.scalar(select(BudgetTransaction)) is None
@@ -400,12 +404,15 @@ def test_submit_rechecks_dynamic_risk_context_and_rejects_stale_ready_review(
assert error_info.value.review["review_id"] != ready_flag["review_id"]
assert error_info.value.review["decision"] == "needs_fix"
assert db.get(ExpenseClaim, claim.id).status == "draft"
assert db.scalar(
select(BusinessEvent).where(
BusinessEvent.aggregate_id == claim.id,
BusinessEvent.event_type == "claim_submitted",
assert (
db.scalar(
select(BusinessEvent).where(
BusinessEvent.aggregate_id == claim.id,
BusinessEvent.event_type == "claim_submitted",
)
)
) is None
is None
)
pre_review_events = list(
db.scalars(
select(BusinessEvent).where(
@@ -429,6 +436,7 @@ def test_legacy_bootstrap_excludes_migration_owned_tables(
monkeypatch.setattr(service, "_seed_agent_assets", lambda: None)
monkeypatch.setattr(service, "_sync_demo_financial_records", lambda: None)
monkeypatch.setattr(service, "_seed_runs_and_logs", lambda: None)
monkeypatch.setattr(TenantRegistryService, "ensure_builtin", lambda self: None)
service._prepare_foundation()
@@ -473,6 +481,7 @@ def test_event_write_is_idempotent_for_same_business_operation() -> None:
def test_submit_claim_creates_case_link_and_structured_event() -> None:
current_user = CurrentUserContext(
tenant_id="default",
username="employee-case@example.com",
name="张三",
role_codes=[],
@@ -536,6 +545,7 @@ def test_payment_event_failure_rolls_back_payment_archive_and_nested_audit(
monkeypatch: pytest.MonkeyPatch,
) -> None:
current_user = CurrentUserContext(
tenant_id="default",
username="finance-case@example.com",
name="财务付款",
role_codes=["finance"],
@@ -639,6 +649,7 @@ def test_application_approval_links_generated_reimbursement_to_same_case() -> No
approved = ExpenseClaimService(db).approve_claim(
application_claim.id,
CurrentUserContext(
tenant_id="default",
username=manager.email,
name=manager.name,
role_codes=["manager"],
@@ -680,6 +691,7 @@ def test_application_approval_links_generated_reimbursement_to_same_case() -> No
def test_payment_records_application_archive_event_in_same_case() -> None:
current_user = CurrentUserContext(
tenant_id="default",
username="finance-archive@example.com",
name="财务付款",
role_codes=["finance"],