完成LSFX Mock第二期稳定随机命中后端实施

This commit is contained in:
wkc
2026-03-22 11:48:22 +08:00
parent 4e4af5d9fb
commit cc209f04e2
12 changed files with 1131 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
from fastapi import BackgroundTasks, UploadFile
from utils.response_builder import ResponseBuilder
from config.settings import settings
from services.phase2_baseline_service import Phase2BaselineService
from services.staff_identity_repository import StaffIdentityRepository
from typing import Dict, List, Union
from dataclasses import dataclass, field
@@ -31,6 +32,22 @@ PHASE1_RULE_CODES = [
"WITHDRAW_CNT",
]
PHASE2_STATEMENT_RULE_CODES = [
"LOW_INCOME_RELATIVE_LARGE_TRANSACTION",
"MULTI_PARTY_GAMBLING_TRANSFER",
"MONTHLY_FIXED_INCOME",
"FIXED_COUNTERPARTY_TRANSFER",
"SALARY_QUICK_TRANSFER",
"SALARY_UNUSED",
]
PHASE2_BASELINE_RULE_CODES = [
"HOUSE_REGISTRATION_MISMATCH",
"PROPERTY_FEE_REGISTRATION_MISMATCH",
"TAX_ASSET_REGISTRATION_MISMATCH",
"SUPPLIER_CONCENTRATION",
]
@dataclass
class FileRecord:
@@ -88,6 +105,8 @@ class FileRecord:
family_id_cards: List[str] = field(default_factory=list)
large_transaction_hit_rules: List[str] = field(default_factory=list)
phase1_hit_rules: List[str] = field(default_factory=list)
phase2_statement_hit_rules: List[str] = field(default_factory=list)
phase2_baseline_hit_rules: List[str] = field(default_factory=list)
class FileService:
@@ -97,10 +116,11 @@ class FileService:
LOG_ID_MIN = settings.INITIAL_LOG_ID
LOG_ID_MAX = 99999
def __init__(self, staff_identity_repository=None):
def __init__(self, staff_identity_repository=None, phase2_baseline_service=None):
self.file_records: Dict[int, FileRecord] = {} # logId -> FileRecord
self.log_counter = settings.INITIAL_LOG_ID
self.staff_identity_repository = staff_identity_repository or StaffIdentityRepository()
self.phase2_baseline_service = phase2_baseline_service or Phase2BaselineService()
def get_file_record(self, log_id: int) -> FileRecord:
"""按 logId 获取已存在的文件记录。"""
@@ -167,6 +187,12 @@ class FileService:
rng, LARGE_TRANSACTION_RULE_CODES, 2, 4
),
"phase1_hit_rules": self._pick_rule_subset(rng, PHASE1_RULE_CODES, 2, 4),
"phase2_statement_hit_rules": self._pick_rule_subset(
rng, PHASE2_STATEMENT_RULE_CODES, 2, 4
),
"phase2_baseline_hit_rules": self._pick_rule_subset(
rng, PHASE2_BASELINE_RULE_CODES, 2, 4
),
}
def _create_file_record(
@@ -191,6 +217,8 @@ class FileService:
family_id_cards: List[str] = None,
large_transaction_hit_rules: List[str] = None,
phase1_hit_rules: List[str] = None,
phase2_statement_hit_rules: List[str] = None,
phase2_baseline_hit_rules: List[str] = None,
parsing: bool = True,
status: int = -5,
) -> FileRecord:
@@ -223,6 +251,8 @@ class FileService:
family_id_cards=list(family_id_cards or []),
large_transaction_hit_rules=list(large_transaction_hit_rules or []),
phase1_hit_rules=list(phase1_hit_rules or []),
phase2_statement_hit_rules=list(phase2_statement_hit_rules or []),
phase2_baseline_hit_rules=list(phase2_baseline_hit_rules or []),
parsing=parsing,
status=status,
)
@@ -231,6 +261,14 @@ class FileService:
"""读取一个员工及其亲属身份范围。"""
return self.staff_identity_repository.select_random_staff_with_families()
def _apply_phase2_baselines(self, file_record: FileRecord) -> None:
"""按当前记录命中的第二期基线规则幂等补齐外部事实。"""
self.phase2_baseline_service.apply(
staff_id_card=file_record.staff_id_card,
family_id_cards=file_record.family_id_cards,
baseline_rule_codes=file_record.phase2_baseline_hit_rules,
)
async def upload_file(
self, group_id: int, file: UploadFile, background_tasks: BackgroundTasks
) -> Dict:
@@ -280,12 +318,15 @@ class FileService:
staff_name=identity_scope["staff_name"],
staff_id_card=identity_scope["staff_id_card"],
family_id_cards=identity_scope["family_id_cards"],
large_transaction_hit_rules=rule_hit_plan["large_transaction_hit_rules"],
phase1_hit_rules=rule_hit_plan["phase1_hit_rules"],
large_transaction_hit_rules=rule_hit_plan.get("large_transaction_hit_rules", []),
phase1_hit_rules=rule_hit_plan.get("phase1_hit_rules", []),
phase2_statement_hit_rules=rule_hit_plan.get("phase2_statement_hit_rules", []),
phase2_baseline_hit_rules=rule_hit_plan.get("phase2_baseline_hit_rules", []),
)
# 存储记录
self.file_records[log_id] = file_record
self._apply_phase2_baselines(file_record)
# 添加后台任务(延迟解析)
background_tasks.add_task(self._delayed_parse, log_id)
@@ -607,12 +648,15 @@ class FileService:
staff_name=identity_scope["staff_name"],
staff_id_card=identity_scope["staff_id_card"],
family_id_cards=identity_scope["family_id_cards"],
large_transaction_hit_rules=rule_hit_plan["large_transaction_hit_rules"],
phase1_hit_rules=rule_hit_plan["phase1_hit_rules"],
large_transaction_hit_rules=rule_hit_plan.get("large_transaction_hit_rules", []),
phase1_hit_rules=rule_hit_plan.get("phase1_hit_rules", []),
phase2_statement_hit_rules=rule_hit_plan.get("phase2_statement_hit_rules", []),
phase2_baseline_hit_rules=rule_hit_plan.get("phase2_baseline_hit_rules", []),
parsing=False,
)
self.file_records[log_id] = file_record
self._apply_phase2_baselines(file_record)
# 返回成功的响应包含logId数组
return {