""" 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"] def test_upload_file_then_upload_status_reads_same_record(monkeypatch): """上传后再查状态时,上传状态接口必须读取同一条真实记录。""" service = FileService() monkeypatch.setattr( service, "_generate_primary_binding", lambda: ("测试主体B", "6222333344445555"), ) background_tasks = BackgroundTasks() file = UploadFile(filename="测试文件.csv", file=io.BytesIO(b"mock")) upload_response = asyncio.run(service.upload_file(1001, file, background_tasks)) log = upload_response["data"]["uploadLogList"][0] monkeypatch.setattr( service, "_build_deterministic_log_detail", lambda *args, **kwargs: (_ for _ in ()).throw( AssertionError("真实记录存在时不应走 deterministic fallback") ), ) status_response = service.get_upload_status(1001, log["logId"]) status_log = status_response["data"]["logs"][0] assert status_log["enterpriseNameList"] == log["enterpriseNameList"] assert status_log["accountNoList"] == log["accountNoList"] assert status_log["bankName"] == log["bankName"] assert status_log["templateName"] == log["templateName"] assert status_log["uploadFileName"] == log["uploadFileName"] assert status_log["trxDateStartId"] == log["trxDateStartId"] assert status_log["trxDateEndId"] == log["trxDateEndId"] assert status_log["enterpriseNameList"] == ["测试主体B"] assert status_log["accountNoList"] == ["6222333344445555"] assert len(status_log["enterpriseNameList"]) == 1 assert len(status_log["accountNoList"]) == 1 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"]