收敛Mock文件记录主体账号绑定模型
This commit is contained in:
@@ -21,6 +21,8 @@ class FileRecord:
|
||||
parsing: bool = True # True表示正在解析
|
||||
|
||||
# 新增字段 - 账号和主体信息
|
||||
primary_enterprise_name: str = ""
|
||||
primary_account_no: str = ""
|
||||
account_no_list: List[str] = field(default_factory=list)
|
||||
enterprise_name_list: List[str] = field(default_factory=list)
|
||||
|
||||
@@ -74,6 +76,27 @@ class FileService:
|
||||
else:
|
||||
return "ZJRCU", "ZJRCU_T251114"
|
||||
|
||||
def _generate_primary_binding(self) -> tuple:
|
||||
"""生成单一稳定的本方主体/本方账号绑定。"""
|
||||
primary_account_no = f"{random.randint(10000000000, 99999999999)}"
|
||||
primary_enterprise_name = "测试主体"
|
||||
return primary_enterprise_name, primary_account_no
|
||||
|
||||
def _generate_primary_binding_from_rng(self, rng: random.Random) -> tuple:
|
||||
"""使用局部随机源生成单一稳定的本方主体/本方账号绑定。"""
|
||||
primary_account_no = f"{rng.randint(10000000000, 99999999999)}"
|
||||
primary_enterprise_name = "测试主体"
|
||||
return primary_enterprise_name, primary_account_no
|
||||
|
||||
def _build_primary_binding_lists(
|
||||
self, primary_enterprise_name: str, primary_account_no: str
|
||||
) -> dict:
|
||||
"""基于主绑定事实源构建列表字段。"""
|
||||
return {
|
||||
"accountNoList": [primary_account_no],
|
||||
"enterpriseNameList": [primary_enterprise_name],
|
||||
}
|
||||
|
||||
async def upload_file(
|
||||
self, group_id: int, file: UploadFile, background_tasks: BackgroundTasks
|
||||
) -> Dict:
|
||||
@@ -100,9 +123,11 @@ class FileService:
|
||||
trx_date_start_id = int(start_date.strftime("%Y%m%d"))
|
||||
trx_date_end_id = int(end_date.strftime("%Y%m%d"))
|
||||
|
||||
# 生成随机账号和主体
|
||||
account_no = f"{random.randint(10000000000, 99999999999)}"
|
||||
enterprise_names = ["测试主体"] if random.random() > 0.3 else [""]
|
||||
# 生成单一主绑定
|
||||
primary_enterprise_name, primary_account_no = self._generate_primary_binding()
|
||||
binding_lists = self._build_primary_binding_lists(
|
||||
primary_enterprise_name, primary_account_no
|
||||
)
|
||||
|
||||
# 创建完整的文件记录
|
||||
file_record = FileRecord(
|
||||
@@ -113,8 +138,10 @@ class FileService:
|
||||
bank_name=bank_name,
|
||||
real_bank_name=bank_name,
|
||||
template_name=template_name,
|
||||
account_no_list=[account_no],
|
||||
enterprise_name_list=enterprise_names,
|
||||
primary_enterprise_name=primary_enterprise_name,
|
||||
primary_account_no=primary_account_no,
|
||||
account_no_list=binding_lists["accountNoList"],
|
||||
enterprise_name_list=binding_lists["enterpriseNameList"],
|
||||
le_id=10000 + random.randint(0, 9999),
|
||||
login_le_id=10000 + random.randint(0, 9999),
|
||||
file_size=random.randint(10000, 100000),
|
||||
@@ -143,19 +170,21 @@ class FileService:
|
||||
str(file_record.log_id): [
|
||||
{
|
||||
"bank": file_record.bank_name,
|
||||
"accountName": file_record.enterprise_name_list[0] if file_record.enterprise_name_list else "",
|
||||
"accountNo": file_record.account_no_list[0] if file_record.account_no_list else "",
|
||||
"accountName": file_record.primary_enterprise_name,
|
||||
"accountNo": file_record.primary_account_no,
|
||||
"currency": "CNY"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uploadLogList": [
|
||||
{
|
||||
"accountNoList": file_record.account_no_list,
|
||||
**self._build_primary_binding_lists(
|
||||
file_record.primary_enterprise_name,
|
||||
file_record.primary_account_no,
|
||||
),
|
||||
"bankName": file_record.bank_name,
|
||||
"dataTypeInfo": file_record.data_type_info,
|
||||
"downloadFileName": file_record.download_file_name,
|
||||
"enterpriseNameList": file_record.enterprise_name_list,
|
||||
"filePackageId": file_record.file_package_id,
|
||||
"fileSize": file_record.file_size,
|
||||
"fileUploadBy": file_record.file_upload_by,
|
||||
@@ -197,7 +226,9 @@ class FileService:
|
||||
if log_id in self.file_records:
|
||||
self.file_records[log_id].parsing = False
|
||||
|
||||
def _generate_deterministic_record(self, log_id: int, group_id: int) -> dict:
|
||||
def _generate_deterministic_record(
|
||||
self, log_id: int, group_id: int, rng: random.Random
|
||||
) -> dict:
|
||||
"""
|
||||
基于 logId 生成确定性的文件记录
|
||||
|
||||
@@ -215,39 +246,40 @@ class FileService:
|
||||
("ZJRCU", "ZJRCU_T251114")
|
||||
]
|
||||
|
||||
bank_name, template_name = random.choice(bank_options)
|
||||
bank_name, template_name = rng.choice(bank_options)
|
||||
|
||||
# 生成交易日期范围
|
||||
end_date = datetime.now()
|
||||
start_date = end_date - timedelta(days=random.randint(90, 365))
|
||||
start_date = end_date - timedelta(days=rng.randint(90, 365))
|
||||
|
||||
# 生成账号和主体
|
||||
account_no = f"{random.randint(10000000000, 99999999999)}"
|
||||
enterprise_names = ["测试主体"] if random.random() > 0.3 else [""]
|
||||
primary_enterprise_name, primary_account_no = self._generate_primary_binding_from_rng(rng)
|
||||
binding_lists = self._build_primary_binding_lists(
|
||||
primary_enterprise_name, primary_account_no
|
||||
)
|
||||
|
||||
return {
|
||||
"accountNoList": [account_no],
|
||||
**binding_lists,
|
||||
"bankName": bank_name,
|
||||
"dataTypeInfo": ["CSV", ","],
|
||||
"downloadFileName": f"测试文件_{log_id}.csv",
|
||||
"enterpriseNameList": enterprise_names,
|
||||
"fileSize": random.randint(10000, 100000),
|
||||
"fileSize": rng.randint(10000, 100000),
|
||||
"fileUploadBy": 448,
|
||||
"fileUploadByUserName": "admin@support.com",
|
||||
"fileUploadTime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"isSplit": 0,
|
||||
"leId": 10000 + random.randint(0, 9999),
|
||||
"leId": 10000 + rng.randint(0, 9999),
|
||||
"logId": log_id,
|
||||
"logMeta": "{\"lostHeader\":[],\"balanceAmount\":\"-1\"}",
|
||||
"logType": "bankstatement",
|
||||
"loginLeId": 10000 + random.randint(0, 9999),
|
||||
"loginLeId": 10000 + rng.randint(0, 9999),
|
||||
"lostHeader": [],
|
||||
"realBankName": bank_name,
|
||||
"rows": 0,
|
||||
"source": "http",
|
||||
"status": -5,
|
||||
"templateName": template_name,
|
||||
"totalRecords": random.randint(100, 300),
|
||||
"totalRecords": rng.randint(100, 300),
|
||||
"trxDateEndId": int(end_date.strftime("%Y%m%d")),
|
||||
"trxDateStartId": int(start_date.strftime("%Y%m%d")),
|
||||
"uploadFileName": f"测试文件_{log_id}.pdf",
|
||||
@@ -257,11 +289,13 @@ class FileService:
|
||||
def _build_log_detail(self, record: FileRecord) -> dict:
|
||||
"""构建日志详情对象"""
|
||||
return {
|
||||
"accountNoList": record.account_no_list,
|
||||
**self._build_primary_binding_lists(
|
||||
record.primary_enterprise_name,
|
||||
record.primary_account_no,
|
||||
),
|
||||
"bankName": record.bank_name,
|
||||
"dataTypeInfo": record.data_type_info,
|
||||
"downloadFileName": record.download_file_name,
|
||||
"enterpriseNameList": record.enterprise_name_list,
|
||||
"fileSize": record.file_size,
|
||||
"fileUploadBy": record.file_upload_by,
|
||||
"fileUploadByUserName": record.file_upload_by_user_name,
|
||||
@@ -333,11 +367,11 @@ class FileService:
|
||||
logs = []
|
||||
|
||||
if log_id:
|
||||
# 使用 logId 作为随机种子,确保相同 logId 返回相同数据
|
||||
random.seed(log_id)
|
||||
# 使用局部随机源,避免污染全局随机状态
|
||||
rng = random.Random(log_id)
|
||||
|
||||
# 生成确定性的文件记录
|
||||
record = self._generate_deterministic_record(log_id, group_id)
|
||||
record = self._generate_deterministic_record(log_id, group_id, rng)
|
||||
logs.append(record)
|
||||
|
||||
# 返回响应
|
||||
|
||||
40
lsfx-mock-server/tests/test_file_service.py
Normal file
40
lsfx-mock-server/tests/test_file_service.py
Normal file
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
FileService 单一主绑定语义测试
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import io
|
||||
|
||||
from fastapi import BackgroundTasks
|
||||
from fastapi.datastructures import UploadFile
|
||||
|
||||
from services.file_service import FileService
|
||||
|
||||
|
||||
def test_upload_file_primary_binding_response(monkeypatch):
|
||||
"""同一 logId 的主绑定必须稳定且只保留一组主体/账号信息。"""
|
||||
service = FileService()
|
||||
|
||||
monkeypatch.setattr(
|
||||
service,
|
||||
"_generate_primary_binding",
|
||||
lambda: ("测试主体A", "6222021234567890"),
|
||||
)
|
||||
|
||||
background_tasks = BackgroundTasks()
|
||||
file = UploadFile(filename="测试文件.csv", file=io.BytesIO(b"mock"))
|
||||
|
||||
response = asyncio.run(service.upload_file(1001, file, background_tasks))
|
||||
|
||||
log = response["data"]["uploadLogList"][0]
|
||||
account_info = response["data"]["accountsOfLog"][str(log["logId"])][0]
|
||||
record = service.file_records[log["logId"]]
|
||||
|
||||
assert log["enterpriseNameList"] == ["测试主体A"]
|
||||
assert log["accountNoList"] == ["6222021234567890"]
|
||||
assert account_info["accountName"] == "测试主体A"
|
||||
assert account_info["accountNo"] == "6222021234567890"
|
||||
assert record.primary_enterprise_name == "测试主体A"
|
||||
assert record.primary_account_no == "6222021234567890"
|
||||
assert record.enterprise_name_list == ["测试主体A"]
|
||||
assert record.account_no_list == ["6222021234567890"]
|
||||
Reference in New Issue
Block a user