Initial commit: InternalAuditInterprise
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
"""知识图谱穿透集成测试(需 PostgreSQL)。
|
||||
|
||||
验证 R2 关键能力:通过关系边的多跳穿透识别"疑似同一实控人",
|
||||
以及本体约束对非法关系的拒绝。对应场景一(政企拆单+隐性实控人,R8)的图谱基础。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from app.datahub.graph_repo import (
|
||||
OntologyViolationError,
|
||||
add_relationship,
|
||||
find_related_entities,
|
||||
upsert_entity,
|
||||
)
|
||||
from app.datahub.ontology import EntityType, RelationshipType
|
||||
|
||||
|
||||
def test_upsert_entity_is_idempotent(session):
|
||||
e1 = upsert_entity(session, EntityType.CUSTOMER, "CUST-001", "客户甲")
|
||||
e2 = upsert_entity(session, EntityType.CUSTOMER, "CUST-001", "客户甲")
|
||||
assert e1.id == e2.id
|
||||
|
||||
|
||||
def test_ontology_violation_rejected(session):
|
||||
contract = upsert_entity(session, EntityType.CONTRACT, "C-1")
|
||||
customer = upsert_entity(session, EntityType.CUSTOMER, "CUST-2")
|
||||
# 合同 —签约→ 客户 方向非法
|
||||
with pytest.raises(OntologyViolationError):
|
||||
add_relationship(session, RelationshipType.SIGNED, contract, customer)
|
||||
|
||||
|
||||
def test_detect_shared_controller_across_customers(session):
|
||||
"""模拟"8 个客户疑似同一实控人":多个客户经法人关联到同一实控自然人。
|
||||
|
||||
构图:每个客户 <-法定代表人- 各自法人;各法人 -关联-> 同一实控人。
|
||||
从实控人出发,应能穿透到全部客户。
|
||||
"""
|
||||
controller = upsert_entity(session, EntityType.LEGAL_PERSON, "PER-CTRL", "实控人")
|
||||
|
||||
customers = []
|
||||
for i in range(8):
|
||||
cust = upsert_entity(session, EntityType.CUSTOMER, f"CUST-{i}", f"政企客户{i}")
|
||||
rep = upsert_entity(session, EntityType.LEGAL_PERSON, f"PER-{i}", f"法人{i}")
|
||||
# 法人 —法定代表人→ 客户
|
||||
add_relationship(session, RelationshipType.LEGAL_REP_OF, rep, cust)
|
||||
# 法人 —关联(亲属/实控)→ 实控人
|
||||
add_relationship(session, RelationshipType.RELATED_TO, rep, controller)
|
||||
customers.append(cust)
|
||||
session.flush()
|
||||
|
||||
related = find_related_entities(session, controller.id, max_depth=3)
|
||||
related_ids = {rid for rid, _ in related}
|
||||
|
||||
# 从实控人 3 跳内应能穿透到全部 8 个客户
|
||||
for cust in customers:
|
||||
assert cust.id in related_ids, f"未穿透到 {cust.business_key}"
|
||||
|
||||
|
||||
def test_traversal_respects_max_depth(session):
|
||||
a = upsert_entity(session, EntityType.LEGAL_PERSON, "A")
|
||||
b = upsert_entity(session, EntityType.LEGAL_PERSON, "B")
|
||||
c = upsert_entity(session, EntityType.CUSTOMER, "C")
|
||||
add_relationship(session, RelationshipType.RELATED_TO, a, b)
|
||||
add_relationship(session, RelationshipType.LEGAL_REP_OF, b, c)
|
||||
session.flush()
|
||||
|
||||
# depth=1:从 A 只能到 B,到不了 C
|
||||
ids_d1 = {rid for rid, _ in find_related_entities(session, a.id, max_depth=1)}
|
||||
assert b.id in ids_d1
|
||||
assert c.id not in ids_d1
|
||||
|
||||
# depth=2:能到 C
|
||||
ids_d2 = {rid for rid, _ in find_related_entities(session, a.id, max_depth=2)}
|
||||
assert c.id in ids_d2
|
||||
Reference in New Issue
Block a user