feat(platform): close AI expense value loop
Add tenant-safe value, telemetry, connector, commercial, and production-readiness foundations.
This commit is contained in:
@@ -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"}
|
||||
|
||||
Reference in New Issue
Block a user