让拉取本行信息链路复用Mock主体账号绑定
This commit is contained in:
@@ -97,6 +97,54 @@ class FileService:
|
|||||||
"enterpriseNameList": [primary_enterprise_name],
|
"enterpriseNameList": [primary_enterprise_name],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _create_file_record(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
log_id: int,
|
||||||
|
group_id: int,
|
||||||
|
file_name: str,
|
||||||
|
download_file_name: str,
|
||||||
|
bank_name: str,
|
||||||
|
template_name: str,
|
||||||
|
primary_enterprise_name: str,
|
||||||
|
primary_account_no: str,
|
||||||
|
file_size: int,
|
||||||
|
total_records: int,
|
||||||
|
trx_date_start_id: int,
|
||||||
|
trx_date_end_id: int,
|
||||||
|
le_id: int,
|
||||||
|
login_le_id: int,
|
||||||
|
parsing: bool = True,
|
||||||
|
status: int = -5,
|
||||||
|
) -> FileRecord:
|
||||||
|
"""创建文件记录并写入主绑定信息。"""
|
||||||
|
binding_lists = self._build_primary_binding_lists(
|
||||||
|
primary_enterprise_name,
|
||||||
|
primary_account_no,
|
||||||
|
)
|
||||||
|
|
||||||
|
return FileRecord(
|
||||||
|
log_id=log_id,
|
||||||
|
group_id=group_id,
|
||||||
|
file_name=file_name,
|
||||||
|
download_file_name=download_file_name,
|
||||||
|
bank_name=bank_name,
|
||||||
|
real_bank_name=bank_name,
|
||||||
|
template_name=template_name,
|
||||||
|
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=le_id,
|
||||||
|
login_le_id=login_le_id,
|
||||||
|
file_size=file_size,
|
||||||
|
total_records=total_records,
|
||||||
|
trx_date_start_id=trx_date_start_id,
|
||||||
|
trx_date_end_id=trx_date_end_id,
|
||||||
|
parsing=parsing,
|
||||||
|
status=status,
|
||||||
|
)
|
||||||
|
|
||||||
async def upload_file(
|
async def upload_file(
|
||||||
self, group_id: int, file: UploadFile, background_tasks: BackgroundTasks
|
self, group_id: int, file: UploadFile, background_tasks: BackgroundTasks
|
||||||
) -> Dict:
|
) -> Dict:
|
||||||
@@ -125,31 +173,23 @@ class FileService:
|
|||||||
|
|
||||||
# 生成单一主绑定
|
# 生成单一主绑定
|
||||||
primary_enterprise_name, primary_account_no = self._generate_primary_binding()
|
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(
|
file_record = self._create_file_record(
|
||||||
log_id=log_id,
|
log_id=log_id,
|
||||||
group_id=group_id,
|
group_id=group_id,
|
||||||
file_name=file.filename,
|
file_name=file.filename,
|
||||||
download_file_name=file.filename,
|
download_file_name=file.filename,
|
||||||
bank_name=bank_name,
|
bank_name=bank_name,
|
||||||
real_bank_name=bank_name,
|
|
||||||
template_name=template_name,
|
template_name=template_name,
|
||||||
primary_enterprise_name=primary_enterprise_name,
|
primary_enterprise_name=primary_enterprise_name,
|
||||||
primary_account_no=primary_account_no,
|
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),
|
file_size=random.randint(10000, 100000),
|
||||||
total_records=random.randint(100, 300),
|
total_records=random.randint(100, 300),
|
||||||
trx_date_start_id=trx_date_start_id,
|
trx_date_start_id=trx_date_start_id,
|
||||||
trx_date_end_id=trx_date_end_id,
|
trx_date_end_id=trx_date_end_id,
|
||||||
parsing=True,
|
le_id=10000 + random.randint(0, 9999),
|
||||||
status=-5
|
login_le_id=10000 + random.randint(0, 9999),
|
||||||
)
|
)
|
||||||
|
|
||||||
# 存储记录
|
# 存储记录
|
||||||
@@ -367,12 +407,15 @@ class FileService:
|
|||||||
logs = []
|
logs = []
|
||||||
|
|
||||||
if log_id:
|
if log_id:
|
||||||
# 使用局部随机源,避免污染全局随机状态
|
if log_id in self.file_records:
|
||||||
rng = random.Random(log_id)
|
logs.append(self._build_log_detail(self.file_records[log_id]))
|
||||||
|
else:
|
||||||
|
# 使用局部随机源,避免污染全局随机状态
|
||||||
|
rng = random.Random(log_id)
|
||||||
|
|
||||||
# 生成确定性的文件记录
|
# 生成确定性的文件记录
|
||||||
record = self._generate_deterministic_record(log_id, group_id, rng)
|
record = self._generate_deterministic_record(log_id, group_id, rng)
|
||||||
logs.append(record)
|
logs.append(record)
|
||||||
|
|
||||||
# 返回响应
|
# 返回响应
|
||||||
return {
|
return {
|
||||||
@@ -416,16 +459,50 @@ class FileService:
|
|||||||
}
|
}
|
||||||
|
|
||||||
def fetch_inner_flow(self, request: Union[Dict, object]) -> Dict:
|
def fetch_inner_flow(self, request: Union[Dict, object]) -> Dict:
|
||||||
"""拉取行内流水(返回随机logId)
|
"""拉取行内流水(创建并保存绑定记录)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
request: 拉取流水请求(保留参数以符合接口规范,当前Mock实现不使用)
|
request: 拉取流水请求(可以是字典或对象)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
流水响应字典,包含随机生成的logId数组
|
流水响应字典,包含创建并保存的logId数组
|
||||||
"""
|
"""
|
||||||
# 随机生成一个logId(范围:10000-99999)
|
# 支持 dict 或对象
|
||||||
log_id = random.randint(10000, 99999)
|
if isinstance(request, dict):
|
||||||
|
group_id = request.get("groupId", 1000)
|
||||||
|
customer_no = request.get("customerNo", "")
|
||||||
|
data_start_date_id = request.get("dataStartDateId", 20240101)
|
||||||
|
data_end_date_id = request.get("dataEndDateId", 20241231)
|
||||||
|
else:
|
||||||
|
group_id = request.groupId
|
||||||
|
customer_no = request.customerNo
|
||||||
|
data_start_date_id = request.dataStartDateId
|
||||||
|
data_end_date_id = request.dataEndDateId
|
||||||
|
|
||||||
|
# 使用递增 logId,确保与上传链路一致
|
||||||
|
self.log_counter += 1
|
||||||
|
log_id = self.log_counter
|
||||||
|
|
||||||
|
primary_enterprise_name, primary_account_no = self._generate_primary_binding()
|
||||||
|
file_record = self._create_file_record(
|
||||||
|
log_id=log_id,
|
||||||
|
group_id=group_id,
|
||||||
|
file_name=f"{customer_no or 'inner_flow'}_{log_id}.csv",
|
||||||
|
download_file_name=f"{customer_no or 'inner_flow'}_{log_id}.csv",
|
||||||
|
bank_name="ZJRCU",
|
||||||
|
template_name="ZJRCU_T251114",
|
||||||
|
primary_enterprise_name=primary_enterprise_name,
|
||||||
|
primary_account_no=primary_account_no,
|
||||||
|
file_size=random.randint(10000, 100000),
|
||||||
|
total_records=random.randint(100, 300),
|
||||||
|
trx_date_start_id=data_start_date_id,
|
||||||
|
trx_date_end_id=data_end_date_id,
|
||||||
|
le_id=10000 + random.randint(0, 9999),
|
||||||
|
login_le_id=10000 + random.randint(0, 9999),
|
||||||
|
parsing=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.file_records[log_id] = file_record
|
||||||
|
|
||||||
# 返回成功的响应,包含logId数组
|
# 返回成功的响应,包含logId数组
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -10,6 +10,18 @@ import os
|
|||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
from main import app
|
from main import app
|
||||||
|
from config.settings import settings
|
||||||
|
from routers.api import file_service
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def reset_file_service_state():
|
||||||
|
"""避免 file_service 单例状态影响测试顺序。"""
|
||||||
|
file_service.file_records.clear()
|
||||||
|
file_service.log_counter = settings.INITIAL_LOG_ID
|
||||||
|
yield
|
||||||
|
file_service.file_records.clear()
|
||||||
|
file_service.log_counter = settings.INITIAL_LOG_ID
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
API 端点测试
|
API 端点测试
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from routers.api import file_service
|
||||||
|
|
||||||
|
|
||||||
def test_root_endpoint(client):
|
def test_root_endpoint(client):
|
||||||
"""测试根路径"""
|
"""测试根路径"""
|
||||||
@@ -87,6 +89,72 @@ def test_fetch_inner_flow_error_501014(client):
|
|||||||
assert data["successResponse"] == False
|
assert data["successResponse"] == False
|
||||||
|
|
||||||
|
|
||||||
|
def test_fetch_inner_flow_followed_by_upload_status(client):
|
||||||
|
"""拉取行内流水后,上传状态查询应命中同一条绑定记录。"""
|
||||||
|
response = client.post(
|
||||||
|
"/watson/api/project/getJZFileOrZjrcuFile",
|
||||||
|
data={
|
||||||
|
"groupId": 1001,
|
||||||
|
"customerNo": "test_customer_002",
|
||||||
|
"dataChannelCode": "test_code",
|
||||||
|
"requestDateId": 20240101,
|
||||||
|
"dataStartDateId": 20240101,
|
||||||
|
"dataEndDateId": 20240131,
|
||||||
|
"uploadUserId": 902001,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
log_id = response.json()["data"][0]
|
||||||
|
|
||||||
|
assert log_id in file_service.file_records
|
||||||
|
record = file_service.file_records[log_id]
|
||||||
|
|
||||||
|
upload_response = client.get(
|
||||||
|
f"/watson/api/project/bs/upload?groupId=1001&logId={log_id}"
|
||||||
|
)
|
||||||
|
assert upload_response.status_code == 200
|
||||||
|
upload_data = upload_response.json()
|
||||||
|
|
||||||
|
assert upload_data["code"] == "200"
|
||||||
|
assert upload_data["successResponse"] is True
|
||||||
|
assert len(upload_data["data"]["logs"]) == 1
|
||||||
|
|
||||||
|
log = upload_data["data"]["logs"][0]
|
||||||
|
assert log["enterpriseNameList"] == [record.primary_enterprise_name]
|
||||||
|
assert log["accountNoList"] == [record.primary_account_no]
|
||||||
|
assert log["enterpriseNameList"][0] == record.primary_enterprise_name
|
||||||
|
assert log["accountNoList"][0] == record.primary_account_no
|
||||||
|
|
||||||
|
|
||||||
|
def test_fetch_inner_flow_marks_pending_complete(client):
|
||||||
|
"""拉取行内流水后,getpendings 应返回未解析状态。"""
|
||||||
|
response = client.post(
|
||||||
|
"/watson/api/project/getJZFileOrZjrcuFile",
|
||||||
|
data={
|
||||||
|
"groupId": 1001,
|
||||||
|
"customerNo": "test_customer_003",
|
||||||
|
"dataChannelCode": "test_code",
|
||||||
|
"requestDateId": 20240101,
|
||||||
|
"dataStartDateId": 20240101,
|
||||||
|
"dataEndDateId": 20240131,
|
||||||
|
"uploadUserId": 902001,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
log_id = response.json()["data"][0]
|
||||||
|
|
||||||
|
pending_response = client.post(
|
||||||
|
"/watson/api/project/upload/getpendings",
|
||||||
|
data={"groupId": 1001, "inprogressList": str(log_id)},
|
||||||
|
)
|
||||||
|
assert pending_response.status_code == 200
|
||||||
|
pending_data = pending_response.json()
|
||||||
|
|
||||||
|
assert pending_data["data"]["parsing"] is False
|
||||||
|
assert len(pending_data["data"]["pendingList"]) == 1
|
||||||
|
assert pending_data["data"]["pendingList"][0]["logId"] == log_id
|
||||||
|
|
||||||
|
|
||||||
def test_get_upload_status_with_log_id(client):
|
def test_get_upload_status_with_log_id(client):
|
||||||
"""测试带 logId 参数查询返回非空 logs"""
|
"""测试带 logId 参数查询返回非空 logs"""
|
||||||
response = client.get("/watson/api/project/bs/upload?groupId=1000&logId=13994")
|
response = client.get("/watson/api/project/bs/upload?groupId=1000&logId=13994")
|
||||||
|
|||||||
@@ -38,3 +38,39 @@ def test_upload_file_primary_binding_response(monkeypatch):
|
|||||||
assert record.primary_account_no == "6222021234567890"
|
assert record.primary_account_no == "6222021234567890"
|
||||||
assert record.enterprise_name_list == ["测试主体A"]
|
assert record.enterprise_name_list == ["测试主体A"]
|
||||||
assert record.account_no_list == ["6222021234567890"]
|
assert record.account_no_list == ["6222021234567890"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_fetch_inner_flow_persists_primary_binding_record(monkeypatch):
|
||||||
|
"""拉取行内流水必须创建并保存绑定记录。"""
|
||||||
|
service = FileService()
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
service,
|
||||||
|
"_generate_primary_binding",
|
||||||
|
lambda: ("行内主体", "6210987654321098"),
|
||||||
|
)
|
||||||
|
|
||||||
|
request = {
|
||||||
|
"groupId": 1001,
|
||||||
|
"customerNo": "test_customer_001",
|
||||||
|
"dataChannelCode": "test_code",
|
||||||
|
"requestDateId": 20240101,
|
||||||
|
"dataStartDateId": 20240101,
|
||||||
|
"dataEndDateId": 20240131,
|
||||||
|
"uploadUserId": 902001,
|
||||||
|
}
|
||||||
|
|
||||||
|
response = service.fetch_inner_flow(request)
|
||||||
|
log_id = response["data"][0]
|
||||||
|
|
||||||
|
assert log_id == service.log_counter
|
||||||
|
assert log_id in service.file_records
|
||||||
|
|
||||||
|
record = service.file_records[log_id]
|
||||||
|
assert record.parsing is False
|
||||||
|
assert record.primary_enterprise_name
|
||||||
|
assert record.primary_account_no
|
||||||
|
assert record.primary_enterprise_name == "行内主体"
|
||||||
|
assert record.primary_account_no == "6210987654321098"
|
||||||
|
assert record.enterprise_name_list == ["行内主体"]
|
||||||
|
assert record.account_no_list == ["6210987654321098"]
|
||||||
|
|||||||
Reference in New Issue
Block a user