完成LSFX Mock第二期稳定随机命中后端实施
This commit is contained in:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user