fix: 统一mock流水可识别身份证来源
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
from utils.response_builder import ResponseBuilder
|
||||
from typing import Dict, Union, List
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
import uuid
|
||||
from typing import Dict, List, Union
|
||||
import logging
|
||||
import random
|
||||
import uuid
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from services.statement_rule_samples import (
|
||||
IDENTITY_CARD_POOL,
|
||||
build_large_transaction_seed_statements,
|
||||
)
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
@@ -17,102 +21,75 @@ class StatementService:
|
||||
# 缓存:logId -> (statements_list, total_count)
|
||||
self._cache: Dict[int, tuple] = {}
|
||||
self.file_service = file_service
|
||||
# 配置日志级别为 INFO
|
||||
logger.info(f"StatementService initialized with empty cache")
|
||||
logger.info("StatementService initialized with empty cache")
|
||||
|
||||
def _resolve_primary_binding(self, log_id: int) -> tuple:
|
||||
"""优先从 FileService 读取真实主绑定,不存在时再走 fallback。"""
|
||||
"""优先从 FileService 读取真实主绑定,不存在时再走 deterministic fallback。"""
|
||||
if self.file_service is not None:
|
||||
record = self.file_service.get_file_record(log_id)
|
||||
if record is not None:
|
||||
return record.primary_enterprise_name, record.primary_account_no
|
||||
|
||||
return "张传伟", f"{random.randint(100000000000000, 999999999999999)}"
|
||||
rng = random.Random(f"binding:{log_id}")
|
||||
return "张传伟", f"{rng.randint(100000000000000, 999999999999999)}"
|
||||
|
||||
def _generate_random_statement(
|
||||
self,
|
||||
index: int,
|
||||
group_id: int,
|
||||
log_id: int,
|
||||
primary_enterprise_name: str,
|
||||
primary_account_no: str,
|
||||
rng: random.Random,
|
||||
) -> Dict:
|
||||
"""生成单条随机流水记录
|
||||
"""生成单条随机噪声流水记录。"""
|
||||
reference_now = datetime(2026, 3, 18, 9, 0, 0)
|
||||
days_ago = rng.randint(0, 365)
|
||||
trx_datetime = reference_now - timedelta(days=days_ago, minutes=rng.randint(0, 1439))
|
||||
trans_amount = round(rng.uniform(10, 10000), 2)
|
||||
|
||||
Args:
|
||||
index: 流水序号
|
||||
group_id: 项目ID
|
||||
log_id: 文件ID
|
||||
primary_enterprise_name: 本方主体名称
|
||||
primary_account_no: 本方账号
|
||||
|
||||
Returns:
|
||||
单条流水记录字典
|
||||
"""
|
||||
# 随机生成交易日期(最近1年内)
|
||||
days_ago = random.randint(0, 365)
|
||||
trx_datetime = datetime.now() - timedelta(days=days_ago)
|
||||
trx_date = trx_datetime.strftime("%Y-%m-%d %H:%M:%S")
|
||||
accounting_date = trx_datetime.strftime("%Y-%m-%d")
|
||||
accounting_date_id = int(trx_datetime.strftime("%Y%m%d"))
|
||||
|
||||
# 生成创建日期(格式:YYYY-MM-DD HH:MM:SS)
|
||||
create_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
# 随机生成交易金额
|
||||
trans_amount = round(random.uniform(10, 10000), 2)
|
||||
|
||||
# 随机决定是收入还是支出
|
||||
if random.random() > 0.5:
|
||||
# 支出
|
||||
if rng.random() > 0.5:
|
||||
dr_amount = trans_amount
|
||||
cr_amount = 0
|
||||
cr_amount = 0.0
|
||||
trans_flag = "P"
|
||||
else:
|
||||
# 收入
|
||||
cr_amount = trans_amount
|
||||
dr_amount = 0
|
||||
dr_amount = 0.0
|
||||
trans_flag = "R"
|
||||
|
||||
# 随机余额
|
||||
balance_amount = round(random.uniform(1000, 50000), 2)
|
||||
|
||||
# 随机客户信息
|
||||
customers = ["小店", "支付宝", "微信支付", "财付通", "美团", "京东", "淘宝", "银行转账"]
|
||||
customer_name = random.choice(customers)
|
||||
customer_account = str(random.randint(100000000, 999999999))
|
||||
|
||||
# 随机交易描述
|
||||
memos = [
|
||||
f"消费_{customer_name}",
|
||||
f"转账_{customer_name}",
|
||||
f"收款_{customer_name}",
|
||||
f"支付_{customer_name}",
|
||||
f"退款_{customer_name}",
|
||||
]
|
||||
user_memo = random.choice(memos)
|
||||
customer_name = rng.choice(
|
||||
["小店", "支付宝", "微信支付", "财付通", "美团", "京东", "淘宝", "银行转账"]
|
||||
)
|
||||
user_memo = rng.choice(
|
||||
[
|
||||
f"消费_{customer_name}",
|
||||
f"转账_{customer_name}",
|
||||
f"收款_{customer_name}",
|
||||
f"支付_{customer_name}",
|
||||
f"退款_{customer_name}",
|
||||
]
|
||||
)
|
||||
|
||||
return {
|
||||
"accountId": 0,
|
||||
"accountMaskNo": primary_account_no,
|
||||
"accountingDate": accounting_date,
|
||||
"accountingDateId": accounting_date_id,
|
||||
"accountingDate": trx_datetime.strftime("%Y-%m-%d"),
|
||||
"accountingDateId": int(trx_datetime.strftime("%Y%m%d")),
|
||||
"archivingFlag": 0,
|
||||
"attachments": 0,
|
||||
"balanceAmount": balance_amount,
|
||||
"balanceAmount": round(rng.uniform(1000, 50000), 2),
|
||||
"bank": "ZJRCU",
|
||||
"bankComments": "",
|
||||
"bankStatementId": 12847662 + index,
|
||||
"bankTrxNumber": uuid.uuid4().hex,
|
||||
"bankStatementId": 0,
|
||||
"bankTrxNumber": "",
|
||||
"batchId": log_id,
|
||||
"cashType": "1",
|
||||
"commentsNum": 0,
|
||||
"crAmount": cr_amount,
|
||||
"createDate": create_date,
|
||||
"createDate": reference_now.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"createdBy": "902001",
|
||||
"cretNo": "230902199012261247",
|
||||
"cretNo": rng.choice(IDENTITY_CARD_POOL),
|
||||
"currency": "CNY",
|
||||
"customerAccountMaskNo": customer_account,
|
||||
"customerAccountMaskNo": str(rng.randint(100000000, 999999999)),
|
||||
"customerBank": "",
|
||||
"customerId": -1,
|
||||
"customerName": customer_name,
|
||||
@@ -138,36 +115,54 @@ class StatementService:
|
||||
"transformDrAmount": 0,
|
||||
"transfromBalanceAmount": 0,
|
||||
"trxBalance": 0,
|
||||
"trxDate": trx_date,
|
||||
"uploadSequnceNumber": index + 1,
|
||||
"userMemo": user_memo
|
||||
"trxDate": trx_datetime.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"uploadSequnceNumber": 0,
|
||||
"userMemo": user_memo,
|
||||
}
|
||||
|
||||
|
||||
def _assign_statement_ids(self, statements: List[Dict], group_id: int, log_id: int) -> List[Dict]:
|
||||
"""为样本与噪声流水统一补齐稳定的流水标识。"""
|
||||
assigned: List[Dict] = []
|
||||
base_id = log_id * 100000
|
||||
for index, statement in enumerate(statements, start=1):
|
||||
item = dict(statement)
|
||||
item["groupId"] = group_id
|
||||
item["batchId"] = log_id
|
||||
item["bankStatementId"] = base_id + index
|
||||
item["bankTrxNumber"] = uuid.uuid5(
|
||||
uuid.NAMESPACE_DNS, f"lsfx-mock-{log_id}-{index}"
|
||||
).hex
|
||||
item["uploadSequnceNumber"] = index
|
||||
item["transAmount"] = round(item.get("drAmount", 0) + item.get("crAmount", 0), 2)
|
||||
assigned.append(item)
|
||||
return assigned
|
||||
|
||||
def _generate_statements(self, group_id: int, log_id: int, count: int) -> List[Dict]:
|
||||
"""生成指定数量的流水记录
|
||||
|
||||
Args:
|
||||
group_id: 项目ID
|
||||
log_id: 文件ID
|
||||
count: 生成数量
|
||||
|
||||
Returns:
|
||||
流水记录列表
|
||||
"""
|
||||
"""生成指定数量的流水记录。"""
|
||||
primary_enterprise_name, primary_account_no = self._resolve_primary_binding(log_id)
|
||||
statements = []
|
||||
for i in range(count):
|
||||
rng = random.Random(f"statement:{log_id}")
|
||||
seeded_statements = build_large_transaction_seed_statements(
|
||||
group_id=group_id,
|
||||
log_id=log_id,
|
||||
primary_enterprise_name=primary_enterprise_name,
|
||||
primary_account_no=primary_account_no,
|
||||
)
|
||||
|
||||
total_count = max(count, len(seeded_statements))
|
||||
statements = list(seeded_statements)
|
||||
for _ in range(total_count - len(seeded_statements)):
|
||||
statements.append(
|
||||
self._generate_random_statement(
|
||||
i,
|
||||
group_id,
|
||||
log_id,
|
||||
primary_enterprise_name,
|
||||
primary_account_no,
|
||||
rng,
|
||||
)
|
||||
)
|
||||
|
||||
statements = self._assign_statement_ids(statements, group_id, log_id)
|
||||
rng.shuffle(statements)
|
||||
return statements
|
||||
|
||||
def _apply_primary_binding(
|
||||
@@ -182,15 +177,7 @@ class StatementService:
|
||||
statement["accountMaskNo"] = primary_account_no
|
||||
|
||||
def get_bank_statement(self, request: Union[Dict, object]) -> Dict:
|
||||
"""获取银行流水列表
|
||||
|
||||
Args:
|
||||
request: 获取银行流水请求(可以是字典或对象)
|
||||
|
||||
Returns:
|
||||
银行流水响应字典
|
||||
"""
|
||||
# 支持 dict 或对象
|
||||
"""获取银行流水列表。"""
|
||||
if isinstance(request, dict):
|
||||
group_id = request.get("groupId", 1000)
|
||||
log_id = request.get("logId", 10000)
|
||||
@@ -202,25 +189,16 @@ class StatementService:
|
||||
page_now = request.pageNow
|
||||
page_size = request.pageSize
|
||||
|
||||
# 检查缓存中是否已有该logId的数据
|
||||
if log_id not in self._cache:
|
||||
# 随机生成总条数(1200-1500之间)
|
||||
total_count = random.randint(1200, 1500)
|
||||
# 生成所有流水记录
|
||||
total_rng = random.Random(f"total:{log_id}")
|
||||
total_count = total_rng.randint(1200, 1500)
|
||||
all_statements = self._generate_statements(group_id, log_id, total_count)
|
||||
# 存入缓存
|
||||
self._cache[log_id] = (all_statements, total_count)
|
||||
|
||||
# 从缓存获取数据
|
||||
all_statements, total_count = self._cache[log_id]
|
||||
primary_enterprise_name, primary_account_no = self._resolve_primary_binding(log_id)
|
||||
self._apply_primary_binding(
|
||||
all_statements,
|
||||
primary_enterprise_name,
|
||||
primary_account_no,
|
||||
)
|
||||
self._apply_primary_binding(all_statements, primary_enterprise_name, primary_account_no)
|
||||
|
||||
# 模拟分页
|
||||
start = (page_now - 1) * page_size
|
||||
end = start + page_size
|
||||
page_data = all_statements[start:end]
|
||||
|
||||
Reference in New Issue
Block a user