Files
zcglxt/backend_new/app/utils/asset_code.py

98 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
资产编码生成工具
使用PostgreSQL Advisory Lock保证并发安全
"""
from datetime import datetime
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.config import settings
async def generate_asset_code(db: AsyncSession) -> str:
"""
生成资产编码
格式: AS + YYYYMMDD + 流水号(4位)
示例: AS202501240001
使用PostgreSQL Advisory Lock保证并发安全
Args:
db: 数据库会话
Returns:
资产编码
"""
# 获取当前日期字符串
date_str = datetime.now().strftime("%Y%m%d")
prefix = f"AS{date_str}"
# 使用Advisory Lock保证并发安全
# 使用日期作为锁ID避免不同日期的锁冲突
lock_id = int(date_str)
try:
# 获取锁
await db.execute(text(f"SELECT pg_advisory_lock({lock_id})"))
# 查询今天最大的序号
result = await db.execute(
text("""
SELECT CAST(SUBSTRING(asset_code FROM 13 FOR 4) AS INTEGER) as max_seq
FROM assets
WHERE asset_code LIKE :prefix
AND deleted_at IS NULL
ORDER BY asset_code DESC
LIMIT 1
"""),
{"prefix": f"{prefix}%"}
)
row = result.fetchone()
max_seq = row[0] if row and row[0] else 0
# 生成新序号
new_seq = max_seq + 1
seq_str = f"{new_seq:04d}" # 补零到4位
# 组合编码
asset_code = f"{prefix}{seq_str}"
return asset_code
finally:
# 释放锁
await db.execute(text(f"SELECT pg_advisory_unlock({lock_id})"))
def validate_asset_code(asset_code: str) -> bool:
"""
验证资产编码格式
Args:
asset_code: 资产编码
Returns:
是否有效
"""
if not asset_code or len(asset_code) != 14:
return False
# 检查前缀
if not asset_code.startswith("AS"):
return False
# 检查日期部分
date_str = asset_code[2:10]
try:
datetime.strptime(date_str, "%Y%m%d")
except ValueError:
return False
# 检查序号部分
seq_str = asset_code[10:]
if not seq_str.isdigit():
return False
return True