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

@@ -79,12 +79,14 @@ def test_ai_application_draft_update_writes_tenant_scoped_event() -> None:
with session_factory() as db:
owner = Employee(
id="owner-1",
tenant_id="tenant-a",
employee_no="E001",
name="张三",
email="owner@example.com",
)
claim = ExpenseClaim(
id="application-1",
tenant_id="tenant-a",
claim_no="AP-DRAFT-001",
employee_id=owner.id,
employee_name=owner.name,
@@ -151,9 +153,10 @@ def test_untrusted_application_path_does_not_write_learning_ledger() -> None:
)
assert db.get(ExpenseClaim, claim.id) is not None
assert db.scalar(
select(BusinessEvent).where(BusinessEvent.aggregate_id == claim.id)
) is not None
assert (
db.scalar(select(BusinessEvent).where(BusinessEvent.aggregate_id == claim.id))
is not None
)
assert list(db.scalars(select(AIDecision)).all()) == []
assert list(db.scalars(select(AIDecisionFeedback)).all()) == []
assert list(db.scalars(select(WorkflowOutcome)).all()) == []
@@ -166,6 +169,23 @@ def test_non_default_tenant_direct_submit_creates_same_tenant_case_link() -> Non
run_id="application-direct-submit-tenant",
tenant_id="tenant-direct-submit",
)
manager = Employee(
id="manager-direct-submit",
tenant_id="tenant-direct-submit",
employee_no="M-DIRECT",
name="直属领导",
email="manager-direct@example.com",
)
owner = Employee(
id="owner-direct-submit",
tenant_id="tenant-direct-submit",
employee_no="E001",
name="张三",
email="owner@example.com",
manager=manager,
)
db.add_all([manager, owner])
db.commit()
service = UserAgentService(db)
submitted = service._create_expense_application_record(
request,
@@ -352,9 +372,7 @@ def test_ai_application_draft_update_deduplicates_identical_snapshot() -> None:
)
events = list(
db.scalars(
select(BusinessEvent).where(BusinessEvent.aggregate_id == claim.id)
).all()
db.scalars(select(BusinessEvent).where(BusinessEvent.aggregate_id == claim.id)).all()
)
assert len(events) == 1
assert events[0].event_type == "claim_draft_updated"
@@ -413,9 +431,7 @@ def test_ai_application_draft_update_keeps_distinct_snapshots_in_same_run() -> N
)
events = list(
db.scalars(
select(BusinessEvent).where(BusinessEvent.aggregate_id == claim.id)
).all()
db.scalars(select(BusinessEvent).where(BusinessEvent.aggregate_id == claim.id)).all()
)
assert len(events) == 2
assert {event.event_type for event in events} == {"claim_draft_updated"}